kernel_proxy.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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"
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/memfs/mem_fs.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/node.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osmman.h"
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "nacl_io/ossocket.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osstat.h"
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/passthroughfs/passthrough_fs.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/path.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/pepper_interface.h"
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/pipe/pipe_node.h"
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/socket/tcp_node.h"
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/socket/udp_node.h"
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/stream/stream_fs.h"
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/typed_fs_factory.h"
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/auto_lock.h"
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/ref_object.h"
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "sdk_util/string_util.h"
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef MAXPATHLEN
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAXPATHLEN 256
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                             exit_handler_(NULL),
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                             signal_emitter_(new EventEmitter) {
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_));
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)   sigwinch_handler_.sa_handler = SIG_DFL;
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochKernelProxy::~KernelProxy() {
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Clean up the MountFactories.
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (FsFactoryMap_t::iterator i = factories_.begin(); i != factories_.end();
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       ++i) {
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    delete i->second;
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  delete ppapi_;
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)
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result;
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = mount("", "/", "passthroughfs", 0, NULL);
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = mount("", "/dev", "dev", 0, NULL);
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open the first three in order to get STDIN, STDOUT, STDERR
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int fd;
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stdin", O_RDONLY);
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 0);
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stdout", O_WRONLY);
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 1);
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fd = open("/dev/stderr", O_WRONLY);
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 2);
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
110bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
111bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#ifdef PROVIDES_SOCKET_API
112bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  host_resolver_.Init(ppapi_);
113bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsInitArgs args;
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.dev = dev_++;
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.ppapi = ppapi_;
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream_mount_.reset(new StreamFs());
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  result = stream_mount_->Init(args);
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = result;
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return rtn;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool KernelProxy::RegisterFsType(const char* fs_type,
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 fuse_operations* fuse_ops) {
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsFactoryMap_t::iterator iter = factories_.find(fs_type);
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iter != factories_.end())
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_[fs_type] = new FuseFsFactory(fuse_ops);
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool KernelProxy::UnregisterFsType(const char* fs_type) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsFactoryMap_t::iterator iter = factories_.find(fs_type);
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iter == factories_.end())
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete iter->second;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_.erase(iter);
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool KernelProxy::RegisterExitHandler(nacl_io_exit_handler_t exit_handler,
149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                      void* user_data) {
150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (exit_handler_ != NULL)
151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  exit_handler_ = exit_handler;
153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  exit_handler_user_data_ = user_data;
154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return true;
155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::open_resource(const char* path) {
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->OpenResource(rel, &node);
1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // OpenResource failed, try Open().
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error = fs->Open(rel, O_RDONLY, &node);
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (error) {
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      errno = error;
1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return -1;
1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(fs, node));
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Init(O_RDONLY);
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AllocateFD(handle, path);
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::open(const char* path, int open_flags) {
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndNode(path, open_flags, &fs, &node);
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(fs, node));
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Init(open_flags);
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AllocateFD(handle, path);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int KernelProxy::pipe(int pipefds[2]) {
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PipeNode* pipe = new PipeNode(stream_mount_.get());
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node(pipe);
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (pipe->Init(O_RDWR) == 0) {
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedKernelHandle handle0(new KernelHandle(stream_mount_, node));
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedKernelHandle handle1(new KernelHandle(stream_mount_, node));
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Should never fail, but...
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (handle0->Init(O_RDONLY) || handle1->Init(O_WRONLY)) {
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EACCES;
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[0] = AllocateFD(handle0);
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[1] = AllocateFD(handle1);
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return 0;
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
22668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  errno = ENOSYS;
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return -1;
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::close(int fd) {
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Remove the FD from the process open file descriptor map
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeFD(fd);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup(int oldfd) {
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string path;
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireHandleAndPath(oldfd, &handle, &path);
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AllocateFD(handle, path);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup2(int oldfd, int newfd) {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If it's the same file handle, just return
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (oldfd == newfd)
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return newfd;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle old_handle;
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string old_path;
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireHandleAndPath(oldfd, &old_handle, &old_path);
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FreeAndReassignFD(newfd, old_handle, old_path);
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::chdir(const char* path) {
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = SetCWD(path);
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return 0;
2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid KernelProxy::exit(int status) {
282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (exit_handler_)
283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    exit_handler_(status, exit_handler_user_data_);
284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getcwd(char* buf, size_t size) {
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (NULL == buf) {
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = EFAULT;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string cwd = GetCWD();
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify the buffer is large enough
2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (size <= cwd.size()) {
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ERANGE;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  strcpy(buf, cwd.c_str());
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buf;
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getwd(char* buf) {
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == buf) {
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EFAULT;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return getcwd(buf, MAXPATHLEN);
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::chmod(const char* path, mode_t mode) {
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int fd = KernelProxy::open(path, O_RDONLY);
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fchmod(fd, mode);
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::utime(const char* filename, const struct utimbuf* times) {
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mkdir(const char* path, mode_t mode) {
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Mkdir(rel, mode);
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::rmdir(const char* path) {
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Rmdir(rel);
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::stat(const char* path, struct stat* buf) {
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = open(path, O_RDONLY);
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fstat(fd, buf);
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mount(const char* source,
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* target,
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* filesystemtype,
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       unsigned long mountflags,
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const void* data) {
3927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string abs_path = GetAbsParts(target).Join();
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find a factory of that type
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsFactoryMap_t::iterator factory = factories_.find(filesystemtype);
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (factory == factories_.end()) {
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ENODEV;
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Create a map of settings
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringMap_t smap;
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  smap["SOURCE"] = source;
4047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  smap["TARGET"] = abs_path;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (data) {
40758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<std::string> elements;
40858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    sdk_util::SplitString(static_cast<const char*>(data), ',', &elements);
40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (std::vector<std::string>::const_iterator it = elements.begin();
41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         it != elements.end(); ++it) {
41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      size_t location = it->find('=');
41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (location != std::string::npos) {
41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string key = it->substr(0, location);
41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string val = it->substr(location + 1);
41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[key] = val;
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[*it] = "TRUE";
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsInitArgs args;
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.dev = dev_++;
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.string_map = smap;
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.ppapi = ppapi_;
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = factory->second->CreateFilesystem(args, &fs);
4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
4317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
4327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
4337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
4347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = AttachFsAtPath(fs, abs_path);
436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::umount(const char* path) {
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = DetachFsAtPath(path);
4467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
4477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Read(buf, nbytes, &cnt);
463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Write(buf, nbytes, &cnt);
481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fstat(int fd, struct stat* buf) {
490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->GetStat(buf);
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
5157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error)
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::fchdir(int fd) {
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedKernelHandle handle;
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string path;
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireHandleAndPath(fd, &handle, &path);
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error) {
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = error;
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!handle->node()->IsaDir()) {
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = ENOTDIR;
5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (path.empty()) {
5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = EBADF;
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = SetCWD(path);
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error) {
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // errno is return value from SetCWD
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = error;
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return 0;
5488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int KernelProxy::ftruncate(int fd, off_t length) {
551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FTruncate(length);
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
56690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fsync(int fd) {
568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FSync();
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::fdatasync(int fd) {
5858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
5868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
5878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::isatty(int fd) {
590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
594effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return 0;
595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
597effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  error = handle->node()->Isatty();
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
600effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return 0;
601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
603effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return 1;
604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::ioctl(int fd, int request, va_list args) {
607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
608bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->node()->VIoctl(request, args);
615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  off_t new_offset;
632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = handle->Seek(offset, whence, &new_offset);
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return new_offset;
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::unlink(const char* path) {
6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
6447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Unlink(rel);
652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::truncate(const char* path, off_t len) {
6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int fd = KernelProxy::open(path, O_WRONLY);
6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (-1 == fd)
6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int result = ftruncate(fd, len);
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  close(fd);
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return result;
6688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::lstat(const char* path, struct stat* buf) {
6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return stat(path, buf);
6728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::rename(const char* path, const char* newpath) {
6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
676f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Path rel;
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
678f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
679f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
680f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
681f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
682f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem newfs;
684f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Path newrel;
6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = AcquireFsAndRelPath(newpath, &newfs, &newrel);
686f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
687f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
688f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
689f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
690f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (newfs.get() != fs.get()) {
692f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Renaming accross mountpoints is not allowed
693f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = EXDEV;
694f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
695f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
696f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
697f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // They already point to the same path
698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rel == newrel)
699f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return 0;
700f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Rename(rel, newrel);
702f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
705f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
706f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
707f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return 0;
7088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::remove(const char* path) {
7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
7137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Remove(rel);
721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(noelallen): Needs implementation.
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fchmod(int fd, int mode) {
731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Error error = AcquireHandle(fd, &handle);
733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::fcntl(int fd, int request, va_list args) {
7421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Error error = 0;
7431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // F_GETFD and F_SETFD are descirptor specific flags that
7451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // are stored in the KernelObject's decriptor map unlink
7461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // F_GETFL and F_SETFL which are handle specific.
7471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (request) {
7481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case F_GETFD: {
7491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int rtn = -1;
7501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      error = GetFDFlags(fd, &rtn);
7511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (error) {
7521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        errno = error;
7531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return -1;
7541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
7551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return rtn;
7561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
7571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case F_SETFD: {
7581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int flags = va_arg(args, int);
7591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      error = SetFDFlags(fd, flags);
7601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (error) {
7611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        errno = error;
7621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return -1;
7631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
7641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return 0;
7651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
7661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
7671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
76868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedKernelHandle handle;
7691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  error = AcquireHandle(fd, &handle);
77068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error) {
77168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    errno = error;
77268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
77368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
77468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int rtn = 0;
7764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->VFcntl(request, &rtn, args);
7774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
7784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
7794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
7804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
7814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return rtn;
78368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
78468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::access(const char* path, int amode) {
7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Path rel;
788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Access(rel, amode);
796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::readlink(const char *path, char *buf, size_t count) {
8048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = EINVAL;
8058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
8068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
8078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::utimes(const char *filename, const struct timeval times[2]) {
8098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = EINVAL;
8108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
8118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
8128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
813eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(noelallen): Needs implementation.
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::link(const char* oldpath, const char* newpath) {
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::symlink(const char* oldpath, const char* newpath) {
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void* KernelProxy::mmap(void* addr,
825868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        size_t length,
826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int prot,
827868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int flags,
828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int fd,
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        size_t offset) {
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We shouldn't be getting anonymous mmaps here.
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert((flags & MAP_ANONYMOUS) == 0);
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(fd != -1);
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MAP_FAILED;
839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* new_addr;
8427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return MAP_FAILED;
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new_addr;
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::munmap(void* addr, size_t length) {
85290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // NOTE: The comment below is from a previous discarded implementation that
85390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tracks mmap'd regions. For simplicity, we no longer do this; because we
85490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // "snapshot" the contents of the file in mmap(), and don't support
85590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // write-back or updating the mapped region when the file is written, holding
85690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on to the KernelHandle is pointless.
85790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
85890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If we ever do, these threading issues should be considered.
85990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
86090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
86190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // WARNING: this function may be called by free().
86290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
86390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // There is a potential deadlock scenario:
86490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 1: open() -> takes lock1 -> free() -> takes lock2
86590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
86690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
86790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note that open() above could be any function that takes a lock that is
86890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // shared with munmap (this includes munmap!)
86990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
87090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // To prevent this, we avoid taking locks in munmap() that are used by other
87190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // nacl_io functions that may call free. Specifically, we only take the
87290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // mmap_lock, which is only shared with mmap() above. There is still a
87390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // possibility of deadlock if mmap() or munmap() calls free(), so this is not
87490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // allowed.
87590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
87690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unfortunately, munmap still needs to acquire other locks; see the call to
87790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // ReleaseHandle below which takes the process lock. This is safe as long as
87890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // this is never executed from free() -- we can be reasonably sure this is
87990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // true, because malloc only makes anonymous mmap() requests, and should only
88090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // be munmapping those allocations. We never add to mmap_info_list_ for
88190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // anonymous maps, so the unmap_list should always be empty when called from
88290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // free().
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
886bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcflush(int fd, int queue_selector) {
887bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
888bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
889bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
890bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
891bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
892bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
893bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
894bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcflush(queue_selector);
895bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
896bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
897bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
898bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
899bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
900bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
901bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
902bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
903bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
904bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
905bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
906bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
907bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
908bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
909bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
910bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
911bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcgetattr(termios_p);
912bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
913bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
914bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
915bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
916bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
917bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
918bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
919bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
920bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcsetattr(int fd, int optional_actions,
921bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch                           const struct termios *termios_p) {
922bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
923bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
924bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
925bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
926bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
927bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
928bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
929bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcsetattr(optional_actions, termios_p);
930bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
931bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
932bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
933bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
934bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
935bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
936bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
937bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
9383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int KernelProxy::kill(pid_t pid, int sig) {
9393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Currently we don't even pretend that other processes exist
9403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // so we can only send a signal to outselves.  For kill(2)
9413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // pid 0 means the current process group and -1 means all the
9423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // processes we have permission to send signals to.
9433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (pid != getpid() && pid != -1 && pid != 0) {
9443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = ESRCH;
9453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
9463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
9473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Raise an event so that select/poll get interrupted.
94968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AUTO_LOCK(signal_emitter_->GetLock())
95068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  signal_emitter_->RaiseEvents_Locked(POLLERR);
9513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (sig) {
9523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH:
953f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (sigwinch_handler_.sa_handler != SIG_IGN &&
954f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          sigwinch_handler_.sa_handler != SIG_DFL) {
955f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        sigwinch_handler_.sa_handler(SIGWINCH);
956f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
9573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
9583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR1:
9603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR2:
9613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
9623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
9643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EINVAL;
9653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
9663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
9673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
9683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
9693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
970f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int KernelProxy::sigaction(int signum, const struct sigaction* action,
971f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           struct sigaction* oaction) {
972f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (action && action->sa_flags & SA_SIGINFO) {
973f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // We don't support SA_SIGINFO (sa_sigaction field) yet
974f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = EINVAL;
975f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
976f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
977f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
9783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (signum) {
9793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Handled signals.
9803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH: {
981f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (oaction)
982f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        *oaction = sigwinch_handler_;
983f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (action) {
984f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        sigwinch_handler_ = *action;
985f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
986f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return 0;
9873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
9883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
9893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Known signals
9903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGHUP:
9913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGINT:
9923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPIPE:
9933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPOLL:
9943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPROF:
9953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTERM:
9963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGCHLD:
9973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGURG:
9983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGFPE:
9993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGILL:
10003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGQUIT:
10013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGSEGV:
10023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTRAP:
1003f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (action && action->sa_handler != SIG_DFL) {
1004f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // Trying to set this action to anything other than SIG_DFL
1005f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // is not yet supported.
1006f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        errno = EINVAL;
1007f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return -1;
1008f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
1009f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1010f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (oaction) {
1011f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        memset(oaction, 0, sizeof(*oaction));
1012f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        oaction->sa_handler = SIG_DFL;
1013f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
1014f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return 0;
1015f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1016f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // KILL and STOP cannot be handled
1017f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SIGKILL:
1018f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SIGSTOP:
1019f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      errno = EINVAL;
1020f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return -1;
10213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
10223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1023f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Unknown signum
10243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  errno = EINVAL;
1025f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return -1;
10263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
10273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1028a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#ifdef PROVIDES_SOCKET_API
1029ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
10303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochint KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
10313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                        fd_set* exceptfds, struct timeval* timeout) {
103268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  fd_set ignore;
103368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<pollfd> pollfds;
103468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
103568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Simplify logic, by using an IGNORE set for any undefined set
103668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(&ignore);
103768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == readfds)
103868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    readfds = &ignore;
103968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == writefds)
104068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    writefds = &ignore;
104168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (NULL == exceptfds)
104268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    exceptfds = &ignore;
104368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
104468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int fd = 0; fd < nfds; fd++) {
10453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    int events = 0;
104668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, readfds))
10473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLIN;
10483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
104968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, writefds))
10503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLOUT;
10513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
105268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (FD_ISSET(fd, exceptfds))
10533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLERR | POLLHUP;
10543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
105568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events) {
105668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfd info;
105768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.fd = fd;
105868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.events = events;
105968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfds.push_back(info);
10603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
106168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
10623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
106368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(readfds);
106468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(writefds);
106568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FD_ZERO(exceptfds);
10663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
106768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // NULL timeout signals wait forever.
106868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int ms_timeout = -1;
106968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (timeout != NULL) {
107068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000);
10713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
107268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // If the timeout is invalid or too long (larger than signed 32 bit).
107368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
107468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) ||
107568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        (ms < 0) || (ms >= INT_MAX)) {
107668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EINVAL;
107768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
10783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
10793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
108068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ms_timeout = static_cast<int>(ms);
10813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
10823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
108368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int result = poll(&pollfds[0], pollfds.size(), ms_timeout);
108468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result == -1)
108568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
10863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
108768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int event_cnt = 0;
108868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t index = 0; index < pollfds.size(); index++) {
108968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pollfd* info = &pollfds[index];
109068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLIN) {
109168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, readfds);
109268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
10933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
109468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLOUT) {
109568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, writefds);
109668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
10973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
109868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & (POLLHUP | POLLERR)) {
109968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, exceptfds);
110068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
11013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
11023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
11033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
110468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return event_cnt;
110568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
110768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)struct PollInfo {
110868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PollInfo() : index(-1) {};
11093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
111068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<struct pollfd*> fds;
111168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int index;
111268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
11133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
111468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)typedef std::map<EventEmitter*, PollInfo> EventPollMap_t;
11153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
11163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochint KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
111768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EventPollMap_t event_map;
11183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
111968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<EventRequest> requests;
11203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  size_t event_cnt = 0;
112168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
112268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int index = 0; static_cast<nfds_t>(index) < nfds; index++) {
11233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    ScopedKernelHandle handle;
112468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    struct pollfd* fd_info = &fds[index];
112568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = AcquireHandle(fd_info->fd, &handle);
112668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
112768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    fd_info->revents = 0;
11283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
11293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If the node isn't open, or somehow invalid, mark it so.
11303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (err != 0) {
113168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
11323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
11333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
11343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
11353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
11363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If it's already signaled, then just capture the event
113768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedEventEmitter emitter(handle->node()->GetEventEmitter());
113868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int events = POLLIN | POLLOUT;
113968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (emitter)
114068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      events = emitter->GetEventStatus();
114168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
114268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events & fd_info->events) {
114368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = events & fd_info->events;
11443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
11453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
11463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
11473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
114868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (NULL == emitter) {
114968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
11503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
11513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
11523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
115368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
115468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Otherwise try to track it.
115568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    PollInfo* info = &event_map[emitter.get()];
115668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->index == -1) {
115768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest request;
115868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.emitter = emitter;
115968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.filter = fd_info->events;
116068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.events = 0;
116168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
116268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info->index = requests.size();
116368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      requests.push_back(request);
116468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
116568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info->fds.push_back(fd_info);
116668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    requests[info->index].filter |= fd_info->events;
11673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
11683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
116968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If nothing is signaled, then we must wait on the event map
11703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (0 == event_cnt) {
117168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EventListenerPoll wait;
117268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = wait.WaitOnAny(&requests[0], requests.size(), timeout);
117368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((err != 0) && (err != ETIMEDOUT)) {
117468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = err;
11753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
11763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
117768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
117868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (size_t rindex = 0; rindex < requests.size(); rindex++) {
117968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest* request = &requests[rindex];
118068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (request->events) {
118168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        PollInfo* poll_info = &event_map[request->emitter.get()];
118268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        for (size_t findex = 0; findex < poll_info->fds.size(); findex++) {
118368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          struct pollfd* fd_info = poll_info->fds[findex];
118468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          uint32_t events = fd_info->events & request->events;
118568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          if (events) {
118668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            fd_info->revents = events;
118768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            event_cnt++;
118868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          }
118968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
119068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
119168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
11923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
11933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
11943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return event_cnt;
11953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
11963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
11973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Socket Functions
1199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
1200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
12064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
12074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
12084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1209a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
12104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PP_Resource new_sock = 0;
12134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Accept(&new_sock, addr, len);
12144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
12154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
12164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
12174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
12184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
12195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode* sock = new TcpNode(stream_mount_.get(), new_sock);
12204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
12215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The SocketNode now holds a reference to the new socket
12224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // so we release ours.
12234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ppapi_->ReleaseResource(new_sock);
1224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error = sock->Init(O_RDWR);
12254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
12264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
12274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
12284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
12294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
12305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node(sock);
12314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedKernelHandle new_handle(new KernelHandle(stream_mount_, node));
1232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error = new_handle->Init(O_RDWR);
12331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (error != 0) {
12341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    errno = error;
12351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return -1;
12361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
12371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
12384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AllocateFD(new_handle);
1239a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
1242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Bind(addr, len);
12523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
12533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
12543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
12553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
12563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
1261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1266a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
12674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
12684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
12694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1270a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
12714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1272a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Connect(addr, len);
12744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
12754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
12763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
12773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
12783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
12793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void KernelProxy::freeaddrinfo(struct addrinfo *res) {
12835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return host_resolver_.freeaddrinfo(res);
12845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
12855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int KernelProxy::getaddrinfo(const char* node, const char* service,
12875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const struct addrinfo* hints,
12885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             struct addrinfo** res) {
12895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return host_resolver_.getaddrinfo(node, service, hints, res);
12905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
12915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1292bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochstruct hostent* KernelProxy::gethostbyname(const char* name) {
1293bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return host_resolver_.gethostbyname(name);
1294bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
1295bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
1297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetPeerName(addr, len);
13073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
13083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
13093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
1316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1317a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1322a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetSockName(addr, len);
13263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
13273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
13283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockopt(int fd,
13354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int lvl,
13364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int optname,
13374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            void* optval,
13384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            socklen_t* len) {
1339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval || NULL == len) {
1340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1345a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
13494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
13504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
13514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
13524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
13534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
13544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::listen(int fd, int backlog) {
1358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->Listen(backlog);
13634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
13644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
13654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
13664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
13674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
13684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recv(int fd,
1372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          void* buf,
1373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          size_t len,
1374a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          int flags) {
1375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
13814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
13824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
13834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1384a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
13854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1386a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
13884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Recv(buf, len, flags, &out_len);
13894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
13904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
13913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1395a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvfrom(int fd,
1398a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              void* buf,
1399a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              size_t len,
1400a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              int flags,
1401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              struct sockaddr* addr,
1402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              socklen_t* addrlen) {
1403a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, recvfrom with a null addr is identical to recv.
1404a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1405a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return recv(fd, buf, len, flags);
1406a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1407a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1408a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf || NULL == addrlen) {
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->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
14224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
14234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
14243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
14253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == msg ) {
1432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1447a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1448a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1449a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
14514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
14524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
14534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1454a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
14554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
14584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Send(buf, len, flags, &out_len);
14594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
14604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
14613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
14623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1467a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendto(int fd,
1468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* buf,
1469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            size_t len,
1470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int flags,
1471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const struct sockaddr* addr,
1472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t addrlen) {
1473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, sendto with a null addr is identical to send.
1474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1475a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return send(fd, buf, len, flags);
1476a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1477a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
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->SendTo(buf, len, flags, addr, addrlen, &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::sendmsg(int fd, const struct msghdr* msg, int flags) {
1501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == msg) {
1502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1513a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::setsockopt(int fd,
1515a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int lvl,
1516a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int optname,
1517a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* optval,
1518a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t len) {
1519a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval) {
1520a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1521a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1523a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1524a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1525a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1526a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1527a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
15294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
15304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
15314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
15324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
15334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
15344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1535a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1536a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1537a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::shutdown(int fd, int how) {
1538a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1539a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Shutdown(how);
15433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
15443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
15453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
15463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
15473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1549a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1550a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1551a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socket(int domain, int type, int protocol) {
1552a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1553a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1556a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1557f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int open_flags = O_RDWR;
1558f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1559f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (type & SOCK_CLOEXEC) {
1560f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#ifdef O_CLOEXEC
1561f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // The NaCl newlib version of fcntl.h doesn't currently define
1562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // O_CLOEXEC.
1563f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO(sbc): remove this guard once it gets added.
1564f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    open_flags |= O_CLOEXEC;
1565f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
1566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    type &= ~SOCK_CLOEXEC;
1567f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1568f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1569f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (type & SOCK_NONBLOCK) {
1570f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    open_flags |= O_NONBLOCK;
1571f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    type &= ~SOCK_NONBLOCK;
1572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1573f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
15745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode* sock = NULL;
15753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (type) {
15763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_DGRAM:
15775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      sock = new UdpNode(stream_mount_.get());
15783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
15793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_STREAM:
15815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      sock = new TcpNode(stream_mount_.get());
15823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
15833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1584f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_SEQPACKET:
1585f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_RDM:
1586f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_RAW:
15873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EPROTONOSUPPORT;
15883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
1589f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    default:
1591f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      errno = EINVAL;
1592f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return -1;
1593a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node(sock);
1596f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Error rtn = sock->Init(O_RDWR);
15974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (rtn != 0) {
15984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = rtn;
15994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
16003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
16013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
16024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
1603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  rtn = handle->Init(open_flags);
16041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (rtn != 0) {
16051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    errno = rtn;
16061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return -1;
16071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
16081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
16094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AllocateFD(handle);
1610a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1611a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1612a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1613a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == sv) {
1614a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1615a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1616a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1617a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1618a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1619a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // socket pairs. Thus, this function always fails.
1620a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_UNIX != domain) {
1621a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EPROTONOSUPPORT;
1622a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1623a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1624a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1625a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1626a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1627a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1628a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1629a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1630a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // We cannot reach this point.
1631a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = ENOSYS;
1632a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1633a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1634a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1635a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1636a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Error error = AcquireHandle(fd, handle);
1637a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1638a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (error) {
1639a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = error;
1640a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1641a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1642a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1643a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1644a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = ENOTSOCK;
1645a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1646a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1647a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1648a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return 0;
1649a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1650a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1651bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif  // PROVIDES_SOCKET_API
1652a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1653bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}  // namespace_nacl_io
1654