kernel_proxy.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file.
4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_proxy.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <assert.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <limits.h>
113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <poll.h>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <pthread.h>
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <stdio.h>
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string.h>
153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <sys/time.h>
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <unistd.h>
173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <iterator>
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "nacl_io/host_resolver.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_wrap_real.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_dev.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_html5fs.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_http.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_mem.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_node.h"
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "nacl_io/mount_node_pipe.h"
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/mount_node_tcp.h"
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/mount_node_udp.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_passthrough.h"
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "nacl_io/mount_stream.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osmman.h"
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "nacl_io/ossocket.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osstat.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/path.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/pepper_interface.h"
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "nacl_io/typed_mount_factory.h"
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/auto_lock.h"
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/ref_object.h"
4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "sdk_util/string_util.h"
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef MAXPATHLEN
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAXPATHLEN 256
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                             sigwinch_handler_(SIG_IGN),
5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                             signal_emitter_(new EventEmitter) {
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochKernelProxy::~KernelProxy() {
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Clean up the MountFactories.
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (MountFactoryMap_t::iterator i = factories_.begin();
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       i != factories_.end();
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       ++i) {
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    delete i->second;
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  delete ppapi_;
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)Error KernelProxy::Init(PepperInterface* ppapi) {
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Error rtn = 0;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi_ = ppapi;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dev_ = 1;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["memfs"] = new TypedMountFactory<MountMem>;
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["dev"] = new TypedMountFactory<MountDev>;
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>;
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["httpfs"] = new TypedMountFactory<MountHttp>;
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result;
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = mount("", "/", "passthroughfs", 0, NULL);
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = mount("", "/dev", "dev", 0, NULL);
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open the first three in order to get STDIN, STDOUT, STDERR
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int fd;
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stdin", O_RDONLY);
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 0);
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stdout", O_WRONLY);
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 1);
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stderr", O_WRONLY);
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 2);
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
109bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
110bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#ifdef PROVIDES_SOCKET_API
111bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  host_resolver_.Init(ppapi_);
112bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t args;
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  stream_mount_.reset(new MountStream());
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  result = stream_mount_->Init(0, args, ppapi);
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = result;
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return rtn;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::open_resource(const char* path) {
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMountNode node;
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = mnt->OpenResource(rel, &node);
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // OpenResource failed, try Open().
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    error = mnt->Open(rel, O_RDONLY, &node);
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (error) {
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      errno = error;
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return -1;
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedKernelHandle handle(new KernelHandle(mnt, node));
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Init(O_RDONLY);
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return AllocateFD(handle);
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::open(const char* path, int open_flags) {
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMountNode node;
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireMountAndNode(path, open_flags, &mnt, &node);
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle(new KernelHandle(mnt, node));
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Init(open_flags);
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return AllocateFD(handle);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int KernelProxy::pipe(int pipefds[2]) {
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  MountNodePipe* pipe = new MountNodePipe(stream_mount_.get());
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedMountNode node(pipe);
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (pipe->Init(S_IREAD | S_IWRITE) == 0) {
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedKernelHandle handle0(new KernelHandle(stream_mount_, node));
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedKernelHandle handle1(new KernelHandle(stream_mount_, node));
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Should never fail, but...
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (handle0->Init(S_IREAD) || handle1->Init(S_IWRITE)) {
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EACCES;
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[0] = AllocateFD(handle0);
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[1] = AllocateFD(handle1);
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return 0;
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  errno = ENOSYS;
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return -1;
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::close(int fd) {
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Remove the FD from the process open file descriptor map
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeFD(fd);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup(int oldfd) {
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(oldfd, &handle);
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return AllocateFD(handle);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup2(int oldfd, int newfd) {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If it's the same file handle, just return
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (oldfd == newfd)
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return newfd;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle old_handle;
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(oldfd, &old_handle);
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeAndReassignFD(newfd, old_handle);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::chdir(const char* path) {
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = SetCWD(path);
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return 0;
2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getcwd(char* buf, size_t size) {
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string cwd = GetCWD();
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size <= 0) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EINVAL;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If size is 0, allocate as much as we need.
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size == 0) {
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size = cwd.size() + 1;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify the buffer is large enough
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (size <= cwd.size()) {
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ERANGE;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Allocate the buffer if needed
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (buf == NULL) {
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buf = static_cast<char*>(malloc(size));
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  strcpy(buf, cwd.c_str());
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buf;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getwd(char* buf) {
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == buf) {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EFAULT;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return getcwd(buf, MAXPATHLEN);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::chmod(const char* path, mode_t mode) {
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int fd = KernelProxy::open(path, O_RDONLY);
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fchmod(fd, mode);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::utime(const char* filename, const struct utimbuf* times) {
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mkdir(const char* path, mode_t mode) {
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Mkdir(rel, mode);
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::rmdir(const char* path) {
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Rmdir(rel);
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::stat(const char* path, struct stat* buf) {
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = open(path, O_RDONLY);
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fstat(fd, buf);
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mount(const char* source,
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* target,
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* filesystemtype,
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       unsigned long mountflags,
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const void* data) {
3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string abs_path = GetAbsParts(target).Join();
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find a factory of that type
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MountFactoryMap_t::iterator factory = factories_.find(filesystemtype);
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (factory == factories_.end()) {
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ENODEV;
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Create a map of settings
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringMap_t smap;
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  smap["SOURCE"] = source;
3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  smap["TARGET"] = abs_path;
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (data) {
37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<std::string> elements;
38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    sdk_util::SplitString(static_cast<const char*>(data), ',', &elements);
38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (std::vector<std::string>::const_iterator it = elements.begin();
38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         it != elements.end(); ++it) {
38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      size_t location = it->find('=');
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (location != std::string::npos) {
38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string key = it->substr(0, location);
38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string val = it->substr(location + 1);
38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[key] = val;
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[*it] = "TRUE";
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = factory->second->CreateMount(dev_++, smap, ppapi_, &mnt);
3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
3987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
3997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
4007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
4017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = AttachMountAtPath(mnt, abs_path);
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::umount(const char* path) {
4127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = DetachMountAtPath(path);
4137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Read(buf, nbytes, &cnt);
430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Write(buf, nbytes, &cnt);
448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fstat(int fd, struct stat* buf) {
457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->GetStat(buf);
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error)
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::fchdir(int fd) {
4908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
4918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
4928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int KernelProxy::ftruncate(int fd, off_t length) {
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FTruncate(length);
503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fsync(int fd) {
512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FSync();
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::fdatasync(int fd) {
5298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
5308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
5318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::isatty(int fd) {
534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->IsaTTY();
542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::ioctl(int fd, int request, va_list args) {
551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
552bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->node()->VIoctl(request, args);
559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  off_t new_offset;
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = handle->Seek(offset, whence, &new_offset);
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return new_offset;
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::unlink(const char* path) {
586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
5887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Unlink(rel);
596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::truncate(const char* path, off_t len) {
6058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
6068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
6078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::lstat(const char* path, struct stat* buf) {
6108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
6118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
6128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::rename(const char* path, const char* newpath) {
6158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
6168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
6178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::remove(const char* path) {
620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
6227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Remove(rel);
630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(noelallen): Needs implementation.
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fchmod(int fd, int mode) {
640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Error error = AcquireHandle(fd, &handle);
642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::fcntl(int fd, int request, va_list args) {
65168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedKernelHandle handle;
65268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
65368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error) {
65468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    errno = error;
65568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
65668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
65768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int rtn = 0;
6594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->VFcntl(request, &rtn, args);
6604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
6614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
6634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return rtn;
66668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
66768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::access(const char* path, int amode) {
6697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Path rel;
671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  error = mnt->Access(rel, amode);
679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::readlink(const char *path, char *buf, size_t count) {
6878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = EINVAL;
6888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
6898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::utimes(const char *filename, const struct timeval times[2]) {
6928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = EINVAL;
6938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
6948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(noelallen): Needs implementation.
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::link(const char* oldpath, const char* newpath) {
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::symlink(const char* oldpath, const char* newpath) {
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void* KernelProxy::mmap(void* addr,
708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        size_t length,
709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int prot,
710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int flags,
711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int fd,
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        size_t offset) {
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We shouldn't be getting anonymous mmaps here.
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert((flags & MAP_ANONYMOUS) == 0);
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(fd != -1);
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MAP_FAILED;
722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* new_addr;
7257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return MAP_FAILED;
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new_addr;
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::munmap(void* addr, size_t length) {
73590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // NOTE: The comment below is from a previous discarded implementation that
73690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tracks mmap'd regions. For simplicity, we no longer do this; because we
73790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // "snapshot" the contents of the file in mmap(), and don't support
73890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // write-back or updating the mapped region when the file is written, holding
73990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on to the KernelHandle is pointless.
74090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
74190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If we ever do, these threading issues should be considered.
74290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
74390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
74490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // WARNING: this function may be called by free().
74590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
74690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // There is a potential deadlock scenario:
74790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 1: open() -> takes lock1 -> free() -> takes lock2
74890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
74990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
75090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note that open() above could be any function that takes a lock that is
75190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // shared with munmap (this includes munmap!)
75290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
75390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // To prevent this, we avoid taking locks in munmap() that are used by other
75490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // nacl_io functions that may call free. Specifically, we only take the
75590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // mmap_lock, which is only shared with mmap() above. There is still a
75690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // possibility of deadlock if mmap() or munmap() calls free(), so this is not
75790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // allowed.
75890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
75990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unfortunately, munmap still needs to acquire other locks; see the call to
76090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // ReleaseHandle below which takes the process lock. This is safe as long as
76190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // this is never executed from free() -- we can be reasonably sure this is
76290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // true, because malloc only makes anonymous mmap() requests, and should only
76390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // be munmapping those allocations. We never add to mmap_info_list_ for
76490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // anonymous maps, so the unmap_list should always be empty when called from
76590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // free().
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
769bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcflush(int fd, int queue_selector) {
770bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
771bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
772bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
773bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
774bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
775bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
776bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
777bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcflush(queue_selector);
778bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
779bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
780bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
781bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
782bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
783bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
784bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
785bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
786bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
787bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
788bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
789bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
790bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
791bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
792bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
793bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
794bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcgetattr(termios_p);
795bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
796bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
797bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
798bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
799bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
800bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
801bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
802bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
803bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcsetattr(int fd, int optional_actions,
804bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                           const struct termios *termios_p) {
805bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
806bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
807bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
808bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
809bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
810bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
811bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
812bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcsetattr(optional_actions, termios_p);
813bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
814bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
815bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
816bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
817bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
818bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
819bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
820bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
8213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int KernelProxy::kill(pid_t pid, int sig) {
8223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Currently we don't even pretend that other processes exist
8233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // so we can only send a signal to outselves.  For kill(2)
8243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // pid 0 means the current process group and -1 means all the
8253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // processes we have permission to send signals to.
8263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (pid != getpid() && pid != -1 && pid != 0) {
8273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = ESRCH;
8283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
8293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
8303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Raise an event so that select/poll get interrupted.
83268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AUTO_LOCK(signal_emitter_->GetLock())
83368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  signal_emitter_->RaiseEvents_Locked(POLLERR);
8343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (sig) {
8353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH:
8363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (sigwinch_handler_ != SIG_IGN)
8373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        sigwinch_handler_(SIGWINCH);
8383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
8393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR1:
8413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR2:
8423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
8433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
8453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EINVAL;
8463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
8473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
8483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
8493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
8503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)sighandler_t KernelProxy::sigset(int signum, sighandler_t handler) {
8523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (signum) {
8533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Handled signals.
8543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH: {
8553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      sighandler_t old_value = sigwinch_handler_;
8563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (handler == SIG_DFL)
8573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        handler = SIG_IGN;
8583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      sigwinch_handler_ = handler;
8593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return old_value;
8603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
8613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Known signals
8633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGHUP:
8643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGINT:
8653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGKILL:
8663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPIPE:
8673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPOLL:
8683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPROF:
8693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTERM:
8703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGCHLD:
8713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGURG:
8723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGFPE:
8733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGILL:
8743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGQUIT:
8753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGSEGV:
8763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTRAP:
8773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (handler == SIG_DFL)
8783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        return SIG_DFL;
8793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
8803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
8813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
8823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  errno = EINVAL;
8833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return SIG_ERR;
8843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
8853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
886a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#ifdef PROVIDES_SOCKET_API
887ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
8883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochint KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
8893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                        fd_set* exceptfds, struct timeval* timeout) {
89068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  fd_set ignore;
89168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<pollfd> pollfds;
89268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
89368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Simplify logic, by using an IGNORE set for any undefined set
89468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(&ignore);
89568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == readfds)
89668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    readfds = &ignore;
89768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == writefds)
89868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    writefds = &ignore;
89968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == exceptfds)
90068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    exceptfds = &ignore;
90168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
90268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int fd = 0; fd < nfds; fd++) {
9033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    int events = 0;
90468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, readfds))
9053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLIN;
9063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
90768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, writefds))
9083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLOUT;
9093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
91068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, exceptfds))
9113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLERR | POLLHUP;
9123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
91368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events) {
91468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfd info;
91568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.fd = fd;
91668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.events = events;
91768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfds.push_back(info);
9183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
91968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
9203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
92168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(readfds);
92268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(writefds);
92368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(exceptfds);
9243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
92568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // NULL timeout signals wait forever.
92668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int ms_timeout = -1;
92768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (timeout != NULL) {
92868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000);
9293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
93068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // If the timeout is invalid or too long (larger than signed 32 bit).
93168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
93268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) ||
93368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        (ms < 0) || (ms >= INT_MAX)) {
93468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EINVAL;
93568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
9363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
9373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
93868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ms_timeout = static_cast<int>(ms);
9393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
9403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
94168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int result = poll(&pollfds[0], pollfds.size(), ms_timeout);
94268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result == -1)
94368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
9443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
94568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int event_cnt = 0;
94668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t index = 0; index < pollfds.size(); index++) {
94768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pollfd* info = &pollfds[index];
94868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLIN) {
94968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, readfds);
95068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
9513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
95268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLOUT) {
95368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, writefds);
95468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
9553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
95668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & (POLLHUP | POLLERR)) {
95768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, exceptfds);
95868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
9593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
9603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
9613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
96268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return event_cnt;
96368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
9643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
96568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)struct PollInfo {
96668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PollInfo() : index(-1) {};
9673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
96868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<struct pollfd*> fds;
96968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int index;
97068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
9713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
97268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)typedef std::map<EventEmitter*, PollInfo> EventPollMap_t;
9733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
9743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochint KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
97568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EventPollMap_t event_map;
9763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
97768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<EventRequest> requests;
9783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  size_t event_cnt = 0;
97968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
98068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int index = 0; static_cast<nfds_t>(index) < nfds; index++) {
9813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    ScopedKernelHandle handle;
98268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    struct pollfd* fd_info = &fds[index];
98368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = AcquireHandle(fd_info->fd, &handle);
98468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
98568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    fd_info->revents = 0;
9863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
9873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If the node isn't open, or somehow invalid, mark it so.
9883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (err != 0) {
98968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
9903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
9913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
9923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
9933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
9943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If it's already signaled, then just capture the event
99568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedEventEmitter emitter(handle->node()->GetEventEmitter());
99668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int events = POLLIN | POLLOUT;
99768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (emitter)
99868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      events = emitter->GetEventStatus();
99968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
100068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events & fd_info->events) {
100168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = events & fd_info->events;
10023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
10033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
10043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
10053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
100668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (NULL == emitter) {
100768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
10083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
10093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
10103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
101168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
101268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Otherwise try to track it.
101368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    PollInfo* info = &event_map[emitter.get()];
101468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->index == -1) {
101568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest request;
101668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.emitter = emitter;
101768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.filter = fd_info->events;
101868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.events = 0;
101968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
102068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info->index = requests.size();
102168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      requests.push_back(request);
102268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
102368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info->fds.push_back(fd_info);
102468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    requests[info->index].filter |= fd_info->events;
10253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
10263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
102768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If nothing is signaled, then we must wait on the event map
10283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (0 == event_cnt) {
102968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EventListenerPoll wait;
103068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = wait.WaitOnAny(&requests[0], requests.size(), timeout);
103168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((err != 0) && (err != ETIMEDOUT)) {
103268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = err;
10333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
10343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
103568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
103668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (size_t rindex = 0; rindex < requests.size(); rindex++) {
103768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest* request = &requests[rindex];
103868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (request->events) {
103968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        PollInfo* poll_info = &event_map[request->emitter.get()];
104068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        for (size_t findex = 0; findex < poll_info->fds.size(); findex++) {
104168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          struct pollfd* fd_info = poll_info->fds[findex];
104268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          uint32_t events = fd_info->events & request->events;
104368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          if (events) {
104468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            fd_info->revents = events;
104568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            event_cnt++;
104668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          }
104768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
104868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
104968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
10503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
10513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
10523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return event_cnt;
10533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
10543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
10553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1056a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Socket Functions
1057a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
1058a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1059a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1060a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1061a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1062a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1063a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
10644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
10654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
10664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1067a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
10684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1069a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
10704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PP_Resource new_sock = 0;
10714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Accept(&new_sock, addr, len);
10724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
10734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
10744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
10754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
10764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  MountNodeSocket* sock = new MountNodeTCP(stream_mount_.get(), new_sock);
10784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // The MountNodeSocket now holds a reference to the new socket
10804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // so we release ours.
10814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ppapi_->ReleaseResource(new_sock);
10824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = sock->Init(S_IREAD | S_IWRITE);
10834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
10844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
10854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
10864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
10874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedMountNode node(sock);
10894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedKernelHandle new_handle(new KernelHandle(stream_mount_, node));
10904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AllocateFD(new_handle);
1091a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1092a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1093a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
1094a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1095a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1096a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1097a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1098a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1099a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Bind(addr, len);
11043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
11053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
11063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
11073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
11083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
11093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
1113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
11194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
11204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
11214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
11234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Connect(addr, len);
11264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
11274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
11283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
11293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
11303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
11313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1134bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochstruct hostent* KernelProxy::gethostbyname(const char* name) {
1135bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return host_resolver_.gethostbyname(name);
1136bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
1137bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
1139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetPeerName(addr, len);
11493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
11503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
11513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
11523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
11533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
11543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
1158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetSockName(addr, len);
11683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
11693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
11703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
11713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
11723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
11733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockopt(int fd,
11774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int lvl,
11784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int optname,
11794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            void* optval,
11804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            socklen_t* len) {
1181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval || NULL == len) {
1182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1189a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
11904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
11914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
11924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
11934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
11944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
11954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
11964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::listen(int fd, int backlog) {
1200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->Listen(backlog);
12054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
12064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
12074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
12084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
12094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
12104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recv(int fd,
1214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          void* buf,
1215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          size_t len,
1216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          int flags) {
1217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1219a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1222a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
12234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
12244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
12254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1226a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
12274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1228a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
12304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Recv(buf, len, flags, &out_len);
12314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
12324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
12333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
12343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
12353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1239a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvfrom(int fd,
1240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              void* buf,
1241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              size_t len,
1242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              int flags,
1243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              struct sockaddr* addr,
1244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              socklen_t* addrlen) {
1245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, recvfrom with a null addr is identical to recv.
1246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return recv(fd, buf, len, flags);
1248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf || NULL == addrlen) {
1251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1253a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
12564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
12574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
12584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
12604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
12634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
12644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
12654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
12663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
12673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
12683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1270a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1271a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1272a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1273a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == msg ) {
1274a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1275a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1278a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1286a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
12934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
12944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
12954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
12974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
13004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Send(buf, len, flags, &out_len);
13014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
13024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
13033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendto(int fd,
1310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* buf,
1311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            size_t len,
1312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int flags,
1313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const struct sockaddr* addr,
1314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t addrlen) {
1315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, sendto with a null addr is identical to send.
1316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1317a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return send(fd, buf, len, flags);
1318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1322a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
13264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
13274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
13284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
13304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
13334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len);
13344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
13354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
13363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
1343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == msg) {
1344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1345a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1353a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1354a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::setsockopt(int fd,
1357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int lvl,
1358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int optname,
1359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* optval,
1360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t len) {
1361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval) {
1362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
13714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
13724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
13734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
13744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
13754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
13764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::shutdown(int fd, int how) {
1380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1383a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Shutdown(how);
13853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
13863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
13873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1392a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1393a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socket(int domain, int type, int protocol) {
1394a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1395a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1398a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  MountNodeSocket* sock = NULL;
14003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (type) {
14013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_DGRAM:
140268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      sock = new MountNodeUDP(stream_mount_.get());
14033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
14043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_STREAM:
140668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      sock = new MountNodeTCP(stream_mount_.get());
14073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
14083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
14103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EPROTONOSUPPORT;
14113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
1412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ScopedMountNode node(sock);
14154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error rtn = sock->Init(S_IREAD | S_IWRITE);
14164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (rtn != 0) {
14174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = rtn;
14184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
14193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
14224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AllocateFD(handle);
1423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1424a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1426a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == sv) {
1427a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // socket pairs. Thus, this function always fails.
1433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_UNIX != domain) {
1434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EPROTONOSUPPORT;
1435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // We cannot reach this point.
1444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = ENOSYS;
1445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1447a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1448a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1449a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Error error = AcquireHandle(fd, handle);
1450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (error) {
1452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = error;
1453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1454a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = ENOTSOCK;
1458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return 0;
1462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1464bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif  // PROVIDES_SOCKET_API
1465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1466bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}  // namespace_nacl_io
1467