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)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/devfs/dev_fs.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/filesystem.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/fusefs/fuse_fs_factory.h"
24bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "nacl_io/host_resolver.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/html5fs/html5_fs.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/httpfs/http_fs.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_wrap_real.h"
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "nacl_io/log.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/memfs/mem_fs.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/node.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osmman.h"
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "nacl_io/ossocket.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osstat.h"
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/passthroughfs/passthrough_fs.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/path.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/pepper_interface.h"
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/pipe/pipe_node.h"
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/socket/tcp_node.h"
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/socket/udp_node.h"
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/stream/stream_fs.h"
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/typed_fs_factory.h"
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/auto_lock.h"
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/ref_object.h"
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "sdk_util/string_util.h"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef MAXPATHLEN
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAXPATHLEN 256
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)KernelProxy::KernelProxy()
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : dev_(0),
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ppapi_(NULL),
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      exit_handler_(NULL),
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      signal_emitter_(new EventEmitter) {
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_));
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sigwinch_handler_.sa_handler = SIG_DFL;
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochKernelProxy::~KernelProxy() {
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Clean up the FsFactories.
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (FsFactoryMap_t::iterator i = factories_.begin(); i != factories_.end();
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       ++i) {
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    delete i->second;
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)Error KernelProxy::Init(PepperInterface* ppapi) {
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Error rtn = 0;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi_ = ppapi;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dev_ = 1;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_["memfs"] = new TypedFsFactory<MemFs>;
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_["dev"] = new TypedFsFactory<DevFs>;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_["html5fs"] = new TypedFsFactory<Html5Fs>;
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_["httpfs"] = new TypedFsFactory<HttpFs>;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_["passthroughfs"] = new TypedFsFactory<PassthroughFs>;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedFilesystem root_fs;
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rtn = MountInternal("", "/", "passthroughfs", 0, NULL, false, &root_fs);
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rtn != 0)
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedFilesystem fs;
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rtn = MountInternal("", "/dev", "dev", 0, NULL, false, &fs);
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rtn != 0)
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    assert(false);
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  dev_fs_ = sdk_util::static_scoped_ref_cast<DevFs>(fs);
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create the filesystem nodes for / and /dev afterward. They can't be
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // created the normal way because the dev filesystem didn't exist yet.
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rtn = CreateFsNode(root_fs);
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rtn != 0)
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    assert(false);
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rtn = CreateFsNode(dev_fs_);
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rtn != 0)
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open the first three in order to get STDIN, STDOUT, STDERR
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int fd;
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stdin", O_RDONLY);
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 0);
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stdout", O_WRONLY);
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 1);
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stderr", O_WRONLY);
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 2);
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
118bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
119bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#ifdef PROVIDES_SOCKET_API
120bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  host_resolver_.Init(ppapi_);
121bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsInitArgs args;
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.dev = dev_++;
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.ppapi = ppapi_;
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream_fs_.reset(new StreamFs());
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int result = stream_fs_->Init(args);
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = result;
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return rtn;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool KernelProxy::RegisterFsType(const char* fs_type,
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 fuse_operations* fuse_ops) {
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsFactoryMap_t::iterator iter = factories_.find(fs_type);
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iter != factories_.end())
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_[fs_type] = new FuseFsFactory(fuse_ops);
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool KernelProxy::UnregisterFsType(const char* fs_type) {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsFactoryMap_t::iterator iter = factories_.find(fs_type);
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iter == factories_.end())
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete iter->second;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_.erase(iter);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool KernelProxy::RegisterExitHandler(nacl_io_exit_handler_t exit_handler,
157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                      void* user_data) {
158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (exit_handler_ != NULL)
159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  exit_handler_ = exit_handler;
161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  exit_handler_user_data_ = user_data;
162effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return true;
163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::open_resource(const char* path) {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->OpenResource(rel, &node);
1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // OpenResource failed, try Open().
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error = fs->Open(rel, O_RDONLY, &node);
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (error) {
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      errno = error;
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return -1;
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(fs, node));
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Init(O_RDONLY);
1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AllocateFD(handle, path);
1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::open(const char* path, int open_flags) {
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndNode(path, open_flags, &fs, &node);
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(fs, node));
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Init(open_flags);
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AllocateFD(handle, path);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int KernelProxy::pipe(int pipefds[2]) {
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PipeNode* pipe = new PipeNode(stream_fs_.get());
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node(pipe);
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (pipe->Init(O_RDWR) == 0) {
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ScopedKernelHandle handle0(new KernelHandle(stream_fs_, node));
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ScopedKernelHandle handle1(new KernelHandle(stream_fs_, node));
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Should never fail, but...
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (handle0->Init(O_RDONLY) || handle1->Init(O_WRONLY)) {
22668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EACCES;
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[0] = AllocateFD(handle0);
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[1] = AllocateFD(handle1);
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return 0;
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  errno = ENOSYS;
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return -1;
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::close(int fd) {
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Remove the FD from the process open file descriptor map
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeFD(fd);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup(int oldfd) {
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string path;
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireHandleAndPath(oldfd, &handle, &path);
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AllocateFD(handle, path);
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup2(int oldfd, int newfd) {
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If it's the same file handle, just return
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (oldfd == newfd)
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return newfd;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle old_handle;
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string old_path;
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireHandleAndPath(oldfd, &old_handle, &old_path);
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FreeAndReassignFD(newfd, old_handle, old_path);
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd;
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::chdir(const char* path) {
2817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = SetCWD(path);
2827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
2837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
2857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return 0;
2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
289effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid KernelProxy::exit(int status) {
290effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (exit_handler_)
291effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    exit_handler_(status, exit_handler_user_data_);
292effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
293effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getcwd(char* buf, size_t size) {
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (NULL == buf) {
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = EFAULT;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string cwd = GetCWD();
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify the buffer is large enough
3037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (size <= cwd.size()) {
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ERANGE;
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  strcpy(buf, cwd.c_str());
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buf;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getwd(char* buf) {
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == buf) {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EFAULT;
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return getcwd(buf, MAXPATHLEN);
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::chmod(const char* path, mode_t mode) {
321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int fd = KernelProxy::open(path, O_RDONLY);
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fchmod(fd, mode);
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::utime(const char* filename, const struct utimbuf* times) {
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mkdir(const char* path, mode_t mode) {
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Mkdir(rel, mode);
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::rmdir(const char* path) {
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Rmdir(rel);
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::stat(const char* path, struct stat* buf) {
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = open(path, O_RDONLY);
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fstat(fd, buf);
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mount(const char* source,
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* target,
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* filesystemtype,
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       unsigned long mountflags,
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const void* data) {
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedFilesystem fs;
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Error error = MountInternal(
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      source, target, filesystemtype, mountflags, data, true, &fs);
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error) {
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    errno = error;
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return -1;
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return 0;
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error KernelProxy::MountInternal(const char* source,
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const char* target,
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const char* filesystemtype,
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 unsigned long mountflags,
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const void* data,
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 bool create_fs_node,
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 ScopedFilesystem* out_filesystem) {
4177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string abs_path = GetAbsParts(target).Join();
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find a factory of that type
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsFactoryMap_t::iterator factory = factories_.find(filesystemtype);
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (factory == factories_.end())
422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ENODEV;
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Create a map of settings
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringMap_t smap;
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  smap["SOURCE"] = source;
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (data) {
42958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<std::string> elements;
43058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    sdk_util::SplitString(static_cast<const char*>(data), ',', &elements);
43158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
43258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (std::vector<std::string>::const_iterator it = elements.begin();
433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         it != elements.end();
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         ++it) {
43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      size_t location = it->find('=');
43658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (location != std::string::npos) {
43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string key = it->substr(0, location);
43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string val = it->substr(location + 1);
43958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[key] = val;
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
44158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[*it] = "TRUE";
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsInitArgs args;
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.dev = dev_++;
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.string_map = smap;
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.ppapi = ppapi_;
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = factory->second->CreateFilesystem(args, &fs);
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error)
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return error;
4557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = AttachFsAtPath(fs, abs_path);
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error)
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return error;
459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (create_fs_node) {
461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    error = CreateFsNode(fs);
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (error)
463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return error;
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *out_filesystem = fs;
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error KernelProxy::CreateFsNode(const ScopedFilesystem& fs) {
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  assert(dev_fs_);
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return dev_fs_->CreateFsNode(fs.get());
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::umount(const char* path) {
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedFilesystem fs;
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Error error = DetachFsAtPath(path, &fs);
4797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
4807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  error = dev_fs_->DestroyFsNode(fs.get());
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error) {
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Ignore any errors here, just log.
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG_ERROR("Unable to destroy FsNode: %s", strerror(error));
488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
5017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Read(buf, nbytes, &cnt);
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
5197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Write(buf, nbytes, &cnt);
520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fstat(int fd, struct stat* buf) {
529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->GetStat(buf);
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
5547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error)
556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::fchdir(int fd) {
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedKernelHandle handle;
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string path;
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireHandleAndPath(fd, &handle, &path);
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error) {
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = error;
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!handle->node()->IsaDir()) {
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = ENOTDIR;
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (path.empty()) {
5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = EBADF;
5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = SetCWD(path);
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error) {
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // errno is return value from SetCWD
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = error;
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return 0;
5878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
58990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int KernelProxy::ftruncate(int fd, off_t length) {
590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
59690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FTruncate(length);
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
60290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
60490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
60590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fsync(int fd) {
607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FSync();
615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::fdatasync(int fd) {
6248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
6258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
6268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::isatty(int fd) {
629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
633effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return 0;
634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
636effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  error = handle->node()->Isatty();
637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
639effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return 0;
640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return 1;
643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::ioctl(int fd, int request, va_list args) {
646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
647bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->node()->VIoctl(request, args);
654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  off_t new_offset;
671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = handle->Seek(offset, whence, &new_offset);
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return new_offset;
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::unlink(const char* path) {
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
6837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
689868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Unlink(rel);
691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::truncate(const char* path, off_t len) {
7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int fd = KernelProxy::open(path, O_WRONLY);
7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (-1 == fd)
7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int result = ftruncate(fd, len);
7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  close(fd);
7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return result;
7078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::lstat(const char* path, struct stat* buf) {
7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return stat(path, buf);
7118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::rename(const char* path, const char* newpath) {
7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
715f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Path rel;
7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
717f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
718f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
719f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
720f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
721f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem newfs;
723f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Path newrel;
7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = AcquireFsAndRelPath(newpath, &newfs, &newrel);
725f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
726f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
727f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
728f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
729f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (newfs.get() != fs.get()) {
731f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Renaming accross mountpoints is not allowed
732f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = EXDEV;
733f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
734f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
735f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
736f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // They already point to the same path
737f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rel == newrel)
738f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return 0;
739f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Rename(rel, newrel);
741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
742f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
744f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
745f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
746f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return 0;
7478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::remove(const char* path) {
7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
7527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Remove(rel);
760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(noelallen): Needs implementation.
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fchmod(int fd, int mode) {
770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Error error = AcquireHandle(fd, &handle);
772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::fcntl(int fd, int request, va_list args) {
7811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Error error = 0;
7821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
783cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // F_GETFD and F_SETFD are descriptor specific flags that
784cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // are stored in the KernelObject's decriptor map unlike
7851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // F_GETFL and F_SETFL which are handle specific.
7861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (request) {
7871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case F_GETFD: {
7881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int rtn = -1;
7891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      error = GetFDFlags(fd, &rtn);
7901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (error) {
7911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        errno = error;
7921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return -1;
7931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
7941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return rtn;
7951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
7961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case F_SETFD: {
7971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int flags = va_arg(args, int);
7981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      error = SetFDFlags(fd, flags);
7991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (error) {
8001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        errno = error;
8011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return -1;
8021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
8031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return 0;
8041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
8051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
8061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
80768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedKernelHandle handle;
8081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  error = AcquireHandle(fd, &handle);
80968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error) {
81068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    errno = error;
81168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
81268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
81368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int rtn = 0;
8154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->VFcntl(request, &rtn, args);
8164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
8174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
8184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
8194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
8204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return rtn;
82268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
82368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::access(const char* path, int amode) {
8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
826eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Path rel;
827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Access(rel, amode);
835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::readlink(const char* path, char* buf, size_t count) {
8438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = EINVAL;
8448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
8458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
8468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
847cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::utimes(const char* filename, const struct timeval times[2]) {
8488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = EINVAL;
8498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
8508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
8518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
852eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(noelallen): Needs implementation.
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::link(const char* oldpath, const char* newpath) {
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::symlink(const char* oldpath, const char* newpath) {
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
863868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void* KernelProxy::mmap(void* addr,
864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        size_t length,
865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int prot,
866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int flags,
867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int fd,
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        size_t offset) {
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We shouldn't be getting anonymous mmaps here.
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert((flags & MAP_ANONYMOUS) == 0);
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(fd != -1);
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
874868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
875868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MAP_FAILED;
878868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* new_addr;
8817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return MAP_FAILED;
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new_addr;
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::munmap(void* addr, size_t length) {
89190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // NOTE: The comment below is from a previous discarded implementation that
89290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tracks mmap'd regions. For simplicity, we no longer do this; because we
89390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // "snapshot" the contents of the file in mmap(), and don't support
89490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // write-back or updating the mapped region when the file is written, holding
89590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on to the KernelHandle is pointless.
89690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
89790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If we ever do, these threading issues should be considered.
89890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
89990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
90090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // WARNING: this function may be called by free().
90190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
90290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // There is a potential deadlock scenario:
90390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 1: open() -> takes lock1 -> free() -> takes lock2
90490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
90590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
90690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note that open() above could be any function that takes a lock that is
90790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // shared with munmap (this includes munmap!)
90890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
90990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // To prevent this, we avoid taking locks in munmap() that are used by other
91090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // nacl_io functions that may call free. Specifically, we only take the
91190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // mmap_lock, which is only shared with mmap() above. There is still a
91290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // possibility of deadlock if mmap() or munmap() calls free(), so this is not
91390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // allowed.
91490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
91590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unfortunately, munmap still needs to acquire other locks; see the call to
91690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // ReleaseHandle below which takes the process lock. This is safe as long as
91790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // this is never executed from free() -- we can be reasonably sure this is
91890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // true, because malloc only makes anonymous mmap() requests, and should only
91990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // be munmapping those allocations. We never add to mmap_info_list_ for
92090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // anonymous maps, so the unmap_list should always be empty when called from
92190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // free().
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
925bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcflush(int fd, int queue_selector) {
926bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
927bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
928bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
929bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
930bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
931bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
932bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
933bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcflush(queue_selector);
934bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
935bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
936bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
937bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
938bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
939bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
940bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
941bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
942bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
943bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
944bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
945bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
946bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
947bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
948bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
949bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
950bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcgetattr(termios_p);
951bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
952bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
953bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
954bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
955bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
956bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
957bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
958bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
959cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::tcsetattr(int fd,
960cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           int optional_actions,
961cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           const struct termios* termios_p) {
962bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
963bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
964bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
965bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
966bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
967bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
968bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
969bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcsetattr(optional_actions, termios_p);
970bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
971bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
972bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
973bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
974bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
975bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
976bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
977bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
9783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int KernelProxy::kill(pid_t pid, int sig) {
9793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Currently we don't even pretend that other processes exist
9803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // so we can only send a signal to outselves.  For kill(2)
9813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // pid 0 means the current process group and -1 means all the
9823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // processes we have permission to send signals to.
9833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (pid != getpid() && pid != -1 && pid != 0) {
9843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = ESRCH;
9853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
9863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
9873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Raise an event so that select/poll get interrupted.
98968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AUTO_LOCK(signal_emitter_->GetLock())
99068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  signal_emitter_->RaiseEvents_Locked(POLLERR);
9913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (sig) {
9923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH:
993f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (sigwinch_handler_.sa_handler != SIG_IGN &&
994f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          sigwinch_handler_.sa_handler != SIG_DFL) {
995f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        sigwinch_handler_.sa_handler(SIGWINCH);
996f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
9973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
9983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR1:
10003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR2:
10013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
10023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
10043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EINVAL;
10053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
10063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
10073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
10083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
10093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1010cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::sigaction(int signum,
1011cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           const struct sigaction* action,
1012f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           struct sigaction* oaction) {
1013f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (action && action->sa_flags & SA_SIGINFO) {
1014f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // We don't support SA_SIGINFO (sa_sigaction field) yet
1015f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = EINVAL;
1016f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
1017f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1018f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (signum) {
10203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Handled signals.
10213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH: {
1022f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (oaction)
1023f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        *oaction = sigwinch_handler_;
1024f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (action) {
1025f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        sigwinch_handler_ = *action;
1026f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
1027f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return 0;
10283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
10293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Known signals
10313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGHUP:
10323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGINT:
10333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPIPE:
10343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPOLL:
10353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPROF:
10363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTERM:
10373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGCHLD:
10383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGURG:
10393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGFPE:
10403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGILL:
10413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGQUIT:
10423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGSEGV:
10433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTRAP:
1044f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (action && action->sa_handler != SIG_DFL) {
1045f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // Trying to set this action to anything other than SIG_DFL
1046f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // is not yet supported.
1047f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        errno = EINVAL;
1048f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return -1;
1049f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
1050f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1051f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (oaction) {
1052f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        memset(oaction, 0, sizeof(*oaction));
1053f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        oaction->sa_handler = SIG_DFL;
1054f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
1055f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return 0;
1056f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1057f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // KILL and STOP cannot be handled
1058f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SIGKILL:
1059f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SIGSTOP:
1060f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      errno = EINVAL;
1061f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return -1;
10623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
10633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1064f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Unknown signum
10653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  errno = EINVAL;
1066f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return -1;
10673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
10683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1069a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#ifdef PROVIDES_SOCKET_API
1070ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1071cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::select(int nfds,
1072cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        fd_set* readfds,
1073cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        fd_set* writefds,
1074cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        fd_set* exceptfds,
1075cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        struct timeval* timeout) {
107668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<pollfd> pollfds;
107768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
107868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int fd = 0; fd < nfds; fd++) {
10793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    int events = 0;
1080c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (readfds && FD_ISSET(fd, readfds)) {
10813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLIN;
1082c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FD_CLR(fd, readfds);
1083c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
10843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1085c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (writefds && FD_ISSET(fd, writefds)) {
10863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLOUT;
1087c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FD_CLR(fd, writefds);
1088c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
10893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1090c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (exceptfds && FD_ISSET(fd, exceptfds)) {
10913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLERR | POLLHUP;
1092c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FD_CLR(fd, exceptfds);
1093c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
10943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
109568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events) {
109668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfd info;
109768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.fd = fd;
109868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.events = events;
109968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfds.push_back(info);
11003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
110168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
11023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
110368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // NULL timeout signals wait forever.
110468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int ms_timeout = -1;
110568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (timeout != NULL) {
110668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000);
11073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
110868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // If the timeout is invalid or too long (larger than signed 32 bit).
110968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
1110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || (ms < 0) ||
1111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        (ms >= INT_MAX)) {
111268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EINVAL;
111368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
11143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
11153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
111668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ms_timeout = static_cast<int>(ms);
11173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
11183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
111968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int result = poll(&pollfds[0], pollfds.size(), ms_timeout);
112068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result == -1)
112168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
11223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
112368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int event_cnt = 0;
112468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t index = 0; index < pollfds.size(); index++) {
112568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pollfd* info = &pollfds[index];
112668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLIN) {
112768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, readfds);
112868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
11293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
113068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLOUT) {
113168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, writefds);
113268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
11333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
113468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & (POLLHUP | POLLERR)) {
113568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, exceptfds);
113668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
11373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
11383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
11393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
114068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return event_cnt;
114168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
114368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)struct PollInfo {
114468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PollInfo() : index(-1) {};
11453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
114668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<struct pollfd*> fds;
114768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int index;
114868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
11493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
115068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)typedef std::map<EventEmitter*, PollInfo> EventPollMap_t;
11513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::poll(struct pollfd* fds, nfds_t nfds, int timeout) {
115368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EventPollMap_t event_map;
11543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
115568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<EventRequest> requests;
11563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  size_t event_cnt = 0;
115768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
115868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int index = 0; static_cast<nfds_t>(index) < nfds; index++) {
11593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    ScopedKernelHandle handle;
116068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    struct pollfd* fd_info = &fds[index];
116168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = AcquireHandle(fd_info->fd, &handle);
116268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
116368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    fd_info->revents = 0;
11643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
11653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If the node isn't open, or somehow invalid, mark it so.
11663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (err != 0) {
116768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
11683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
11693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
11703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
11713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
11723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If it's already signaled, then just capture the event
117368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedEventEmitter emitter(handle->node()->GetEventEmitter());
117468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int events = POLLIN | POLLOUT;
117568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (emitter)
117668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      events = emitter->GetEventStatus();
117768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
117868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events & fd_info->events) {
117968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = events & fd_info->events;
11803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
11813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
11823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
11833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
118468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (NULL == emitter) {
118568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
11863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
11873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
11883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
118968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
119068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Otherwise try to track it.
119168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    PollInfo* info = &event_map[emitter.get()];
119268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->index == -1) {
119368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest request;
119468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.emitter = emitter;
119568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.filter = fd_info->events;
119668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.events = 0;
119768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
119868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info->index = requests.size();
119968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      requests.push_back(request);
120068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
120168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info->fds.push_back(fd_info);
120268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    requests[info->index].filter |= fd_info->events;
12033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
12043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
120568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If nothing is signaled, then we must wait on the event map
12063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (0 == event_cnt) {
120768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EventListenerPoll wait;
120868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = wait.WaitOnAny(&requests[0], requests.size(), timeout);
120968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((err != 0) && (err != ETIMEDOUT)) {
121068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = err;
12113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
12123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
121368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
121468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (size_t rindex = 0; rindex < requests.size(); rindex++) {
121568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest* request = &requests[rindex];
121668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (request->events) {
121768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        PollInfo* poll_info = &event_map[request->emitter.get()];
121868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        for (size_t findex = 0; findex < poll_info->fds.size(); findex++) {
121968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          struct pollfd* fd_info = poll_info->fds[findex];
122068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          uint32_t events = fd_info->events & request->events;
122168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          if (events) {
122268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            fd_info->revents = events;
122368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            event_cnt++;
122468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          }
122568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
122668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
122768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
12283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
12293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
12303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return event_cnt;
12313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
12323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Socket Functions
1234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
1235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1236a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1239a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
12414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
12424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
12434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
12454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PP_Resource new_sock = 0;
12484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Accept(&new_sock, addr, len);
12494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
12504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
12514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
12524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
12534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SocketNode* sock = new TcpNode(stream_fs_.get(), new_sock);
12554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
12565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The SocketNode now holds a reference to the new socket
12574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // so we release ours.
12584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ppapi_->ReleaseResource(new_sock);
1259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error = sock->Init(O_RDWR);
12604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
12614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
12624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
12634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
12644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
12655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node(sock);
1266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedKernelHandle new_handle(new KernelHandle(stream_fs_, node));
1267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error = new_handle->Init(O_RDWR);
12681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (error != 0) {
12691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    errno = error;
12701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return -1;
12711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
12721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
12734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AllocateFD(new_handle);
1274a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1275a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
1277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1278a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Bind(addr, len);
12873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
12883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
12893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
12903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
12913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
1296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
13024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
13034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
13044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
13064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Connect(addr, len);
13094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
13104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
13113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void KernelProxy::freeaddrinfo(struct addrinfo* res) {
13185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return host_resolver_.freeaddrinfo(res);
13195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
13205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::getaddrinfo(const char* node,
1322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             const char* service,
13235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const struct addrinfo* hints,
13245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             struct addrinfo** res) {
13255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return host_resolver_.getaddrinfo(node, service, hints, res);
13265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
13275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1328bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochstruct hostent* KernelProxy::gethostbyname(const char* name) {
1329bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return host_resolver_.gethostbyname(name);
1330bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
1331bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
1333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1337a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1338a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetPeerName(addr, len);
13433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
13443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
13453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
1352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1353a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1354a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetSockName(addr, len);
13623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
13633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
13643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockopt(int fd,
13714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int lvl,
13724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int optname,
13734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            void* optval,
13744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            socklen_t* len) {
1375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval || NULL == len) {
1376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1383a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
13854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
13864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
13874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
13884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
13894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
13904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1392a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1393a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::listen(int fd, int backlog) {
1394a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1395a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->Listen(backlog);
13994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
14004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
14014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
14024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
14034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
14044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1405a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1406a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ssize_t KernelProxy::recv(int fd, void* buf, size_t len, int flags) {
1408a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
14144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
14154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
14164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
14184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1419a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
14214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Recv(buf, len, flags, &out_len);
14224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
14234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
14243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
14253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvfrom(int fd,
1431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              void* buf,
1432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              size_t len,
1433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              int flags,
1434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              struct sockaddr* addr,
1435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              socklen_t* addrlen) {
1436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, recvfrom with a null addr is identical to recv.
1437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return recv(fd, buf, len, flags);
1439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf || NULL == addrlen) {
1442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
14474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
14484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
14494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
14514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
14544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
14554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
14564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
14573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
14583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (NULL == msg) {
1465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1467a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1475a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1476a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1477a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1478a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1479a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1480a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1481a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1482a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1483a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
14844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
14854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
14864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1487a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
14884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1489a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
14914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Send(buf, len, flags, &out_len);
14924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
14934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
14943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
14953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1498a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1499a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1500a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendto(int fd,
1501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* buf,
1502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            size_t len,
1503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int flags,
1504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const struct sockaddr* addr,
1505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t addrlen) {
1506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, sendto with a null addr is identical to send.
1507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return send(fd, buf, len, flags);
1509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1513a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1515a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1516a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
15174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
15184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
15194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1520a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
15214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
15244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len);
15254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
15264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
15273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
15283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
15293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1531a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1532a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
1534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == msg) {
1535a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1536a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1537a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1538a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1539a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1542a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1543a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1544a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1545a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1546a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1547a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::setsockopt(int fd,
1548a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int lvl,
1549a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int optname,
1550a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* optval,
1551a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t len) {
1552a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval) {
1553a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1556a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1557a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1558a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1559a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1560a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
15624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
15634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
15644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
15654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
15664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
15674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::shutdown(int fd, int how) {
1571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Shutdown(how);
15763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
15773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
15783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
15793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
15803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1583a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socket(int domain, int type, int protocol) {
1585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1586a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1587a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1588a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1589a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int open_flags = O_RDWR;
1591f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1592f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (type & SOCK_CLOEXEC) {
1593f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#ifdef O_CLOEXEC
1594f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // The NaCl newlib version of fcntl.h doesn't currently define
1595f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // O_CLOEXEC.
1596f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO(sbc): remove this guard once it gets added.
1597f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    open_flags |= O_CLOEXEC;
1598f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
1599f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    type &= ~SOCK_CLOEXEC;
1600f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1601f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (type & SOCK_NONBLOCK) {
1603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    open_flags |= O_NONBLOCK;
1604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    type &= ~SOCK_NONBLOCK;
1605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
16075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode* sock = NULL;
16083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (type) {
16093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_DGRAM:
1610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      sock = new UdpNode(stream_fs_.get());
16113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
16123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
16133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_STREAM:
1614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      sock = new TcpNode(stream_fs_.get());
16153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
16163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_SEQPACKET:
1618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_RDM:
1619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_RAW:
16203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EPROTONOSUPPORT;
16213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
1622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    default:
1624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      errno = EINVAL;
1625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return -1;
1626a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1627a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
16285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node(sock);
1629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Error rtn = sock->Init(O_RDWR);
16304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (rtn != 0) {
16314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = rtn;
16324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
16333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
16343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(stream_fs_, node));
1636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  rtn = handle->Init(open_flags);
16371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (rtn != 0) {
16381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    errno = rtn;
16391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return -1;
16401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
16411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
16424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AllocateFD(handle);
1643a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1644a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1645a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1646a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == sv) {
1647a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1648a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1649a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1650a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1651a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1652a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // socket pairs. Thus, this function always fails.
1653a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_UNIX != domain) {
1654a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EPROTONOSUPPORT;
1655a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1656a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1657a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1658a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1659a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1660a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1661a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1662a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1663a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // We cannot reach this point.
1664a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = ENOSYS;
1665a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1666a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1667a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1668a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1669a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Error error = AcquireHandle(fd, handle);
1670a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1671a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (error) {
1672a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = error;
1673a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1674a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1675a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1676a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1677a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = ENOTSOCK;
1678a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1679a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1680a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1681a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return 0;
1682a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1683a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1684bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif  // PROVIDES_SOCKET_API
1685a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1686bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}  // namespace_nacl_io
1687