1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file.
4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_proxy.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <assert.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <limits.h>
113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <poll.h>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <pthread.h>
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <stdio.h>
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string.h>
153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <sys/time.h>
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <unistd.h>
173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <iterator>
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/devfs/dev_fs.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/filesystem.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/fusefs/fuse_fs_factory.h"
24bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "nacl_io/host_resolver.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/html5fs/html5_fs.h"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/httpfs/http_fs.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_wrap_real.h"
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "nacl_io/log.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/memfs/mem_fs.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/node.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osmman.h"
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "nacl_io/ossocket.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osstat.h"
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/passthroughfs/passthrough_fs.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/path.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/pepper_interface.h"
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/pipe/pipe_node.h"
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/socket/tcp_node.h"
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/socket/udp_node.h"
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/stream/stream_fs.h"
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/typed_fs_factory.h"
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/auto_lock.h"
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/ref_object.h"
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "sdk_util/string_util.h"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef MAXPATHLEN
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAXPATHLEN 256
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)KernelProxy::KernelProxy()
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : dev_(0),
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ppapi_(NULL),
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      exit_callback_(NULL),
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      exit_callback_user_data_(NULL),
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      mount_callback_(NULL),
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      mount_callback_user_data_(NULL),
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      signal_emitter_(new EventEmitter) {
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_));
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sigwinch_handler_.sa_handler = SIG_DFL;
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochKernelProxy::~KernelProxy() {
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Clean up the FsFactories.
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (FsFactoryMap_t::iterator i = factories_.begin(); i != factories_.end();
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       ++i) {
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    delete i->second;
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)Error KernelProxy::Init(PepperInterface* ppapi) {
7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Error rtn = 0;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi_ = ppapi;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dev_ = 1;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_["memfs"] = new TypedFsFactory<MemFs>;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_["dev"] = new TypedFsFactory<DevFs>;
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_["html5fs"] = new TypedFsFactory<Html5Fs>;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_["httpfs"] = new TypedFsFactory<HttpFs>;
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_["passthroughfs"] = new TypedFsFactory<PassthroughFs>;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedFilesystem root_fs;
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rtn = MountInternal("", "/", "passthroughfs", 0, NULL, false, &root_fs);
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rtn != 0)
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedFilesystem fs;
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rtn = MountInternal("", "/dev", "dev", 0, NULL, false, &fs);
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rtn != 0)
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    assert(false);
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  dev_fs_ = sdk_util::static_scoped_ref_cast<DevFs>(fs);
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create the filesystem nodes for / and /dev afterward. They can't be
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // created the normal way because the dev filesystem didn't exist yet.
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rtn = CreateFsNode(root_fs);
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rtn != 0)
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    assert(false);
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rtn = CreateFsNode(dev_fs_);
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rtn != 0)
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open the first three in order to get STDIN, STDOUT, STDERR
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int fd;
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  fd = open("/dev/stdin", O_RDONLY, 0);
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 0);
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  fd = open("/dev/stdout", O_WRONLY, 0);
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 1);
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  fd = open("/dev/stderr", O_WRONLY, 0);
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  assert(fd == 2);
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (fd < 0)
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = errno;
121bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
122bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#ifdef PROVIDES_SOCKET_API
123bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  host_resolver_.Init(ppapi_);
124bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsInitArgs args;
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.dev = dev_++;
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.ppapi = ppapi_;
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  stream_fs_.reset(new StreamFs());
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int result = stream_fs_->Init(args);
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (result != 0) {
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    assert(false);
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rtn = result;
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return rtn;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool KernelProxy::RegisterFsType(const char* fs_type,
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 fuse_operations* fuse_ops) {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsFactoryMap_t::iterator iter = factories_.find(fs_type);
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iter != factories_.end())
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_[fs_type] = new FuseFsFactory(fuse_ops);
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool KernelProxy::UnregisterFsType(const char* fs_type) {
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsFactoryMap_t::iterator iter = factories_.find(fs_type);
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iter == factories_.end())
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete iter->second;
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  factories_.erase(iter);
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid KernelProxy::SetExitCallback(nacl_io_exit_callback_t exit_callback,
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                  void* user_data) {
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  exit_callback_ = exit_callback;
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  exit_callback_user_data_ = user_data;
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid KernelProxy::SetMountCallback(nacl_io_mount_callback_t mount_callback,
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                   void* user_data) {
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  mount_callback_ = mount_callback;
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  mount_callback_user_data_ = user_data;
169effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
170effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::open_resource(const char* path) {
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->OpenResource(rel, &node);
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // OpenResource failed, try Open().
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error = fs->Open(rel, O_RDONLY, &node);
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (error) {
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      errno = error;
1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return -1;
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(fs, node));
1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Init(O_RDONLY);
1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AllocateFD(handle, path);
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint KernelProxy::open(const char* path, int open_flags, mode_t mode) {
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Error error = AcquireFsAndNode(path, open_flags, mode, &fs, &node);
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(fs, node));
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Init(open_flags);
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AllocateFD(handle, path);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int KernelProxy::pipe(int pipefds[2]) {
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PipeNode* pipe = new PipeNode(stream_fs_.get());
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node(pipe);
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (pipe->Init(O_RDWR) == 0) {
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ScopedKernelHandle handle0(new KernelHandle(stream_fs_, node));
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ScopedKernelHandle handle1(new KernelHandle(stream_fs_, node));
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Should never fail, but...
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (handle0->Init(O_RDONLY) || handle1->Init(O_WRONLY)) {
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EACCES;
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[0] = AllocateFD(handle0);
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pipefds[1] = AllocateFD(handle1);
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return 0;
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  errno = ENOSYS;
24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return -1;
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::close(int fd) {
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Remove the FD from the process open file descriptor map
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeFD(fd);
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup(int oldfd) {
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string path;
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireHandleAndPath(oldfd, &handle, &path);
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AllocateFD(handle, path);
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup2(int oldfd, int newfd) {
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If it's the same file handle, just return
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (oldfd == newfd)
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return newfd;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle old_handle;
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string old_path;
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireHandleAndPath(oldfd, &old_handle, &old_path);
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FreeAndReassignFD(newfd, old_handle, old_path);
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::chdir(const char* path) {
2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = SetCWD(path);
2887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
2897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
2907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return 0;
2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
295effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid KernelProxy::exit(int status) {
296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (exit_callback_)
297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    exit_callback_(status, exit_callback_user_data_);
298effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
299effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getcwd(char* buf, size_t size) {
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (NULL == buf) {
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = EFAULT;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string cwd = GetCWD();
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify the buffer is large enough
3097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (size <= cwd.size()) {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ERANGE;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  strcpy(buf, cwd.c_str());
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buf;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getwd(char* buf) {
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == buf) {
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EFAULT;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return getcwd(buf, MAXPATHLEN);
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::chmod(const char* path, mode_t mode) {
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int fd = open(path, O_RDONLY, mode);
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fchmod(fd, mode);
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mkdir(const char* path, mode_t mode) {
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Mkdir(rel, mode);
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::rmdir(const char* path) {
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Rmdir(rel);
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::stat(const char* path, struct stat* buf) {
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int fd = open(path, O_RDONLY, 0);
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fstat(fd, buf);
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mount(const char* source,
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* target,
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* filesystemtype,
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       unsigned long mountflags,
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const void* data) {
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedFilesystem fs;
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Error error = MountInternal(
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      source, target, filesystemtype, mountflags, data, true, &fs);
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error) {
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    errno = error;
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return -1;
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return 0;
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error KernelProxy::MountInternal(const char* source,
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const char* target,
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const char* filesystemtype,
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 unsigned long mountflags,
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const void* data,
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 bool create_fs_node,
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 ScopedFilesystem* out_filesystem) {
4197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string abs_path = GetAbsParts(target).Join();
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find a factory of that type
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsFactoryMap_t::iterator factory = factories_.find(filesystemtype);
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (factory == factories_.end()) {
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Unknown filesystem type: %s", filesystemtype);
425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ENODEV;
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Create a map of settings
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringMap_t smap;
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  smap["SOURCE"] = source;
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (data) {
43358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    std::vector<std::string> elements;
43458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    sdk_util::SplitString(static_cast<const char*>(data), ',', &elements);
43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
43658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (std::vector<std::string>::const_iterator it = elements.begin();
437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         it != elements.end();
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         ++it) {
43958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      size_t location = it->find('=');
44058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (location != std::string::npos) {
44158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string key = it->substr(0, location);
44258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        std::string val = it->substr(location + 1);
44358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[key] = val;
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
44558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        smap[*it] = "TRUE";
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FsInitArgs args;
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.dev = dev_++;
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.string_map = smap;
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args.ppapi = ppapi_;
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = factory->second->CreateFilesystem(args, &fs);
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error)
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return error;
4597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = AttachFsAtPath(fs, abs_path);
461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error)
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return error;
463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (create_fs_node) {
465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    error = CreateFsNode(fs);
466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (error) {
467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      DetachFsAtPath(abs_path, &fs);
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return error;
469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *out_filesystem = fs;
473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
474116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (mount_callback_) {
475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    mount_callback_(source,
476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    target,
477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    filesystemtype,
478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    mountflags,
479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    data,
480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    fs->dev(),
481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    mount_callback_user_data_);
482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Error KernelProxy::CreateFsNode(const ScopedFilesystem& fs) {
488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  assert(dev_fs_);
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return dev_fs_->CreateFsNode(fs.get());
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::umount(const char* path) {
494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedFilesystem fs;
495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Error error = DetachFsAtPath(path, &fs);
4967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
4977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  error = dev_fs_->DestroyFsNode(fs.get());
502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (error) {
503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Ignore any errors here, just log.
504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG_ERROR("Unable to destroy FsNode: %s", strerror(error));
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
5187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Read(buf, nbytes, &cnt);
519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
5367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Write(buf, nbytes, &cnt);
537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fstat(int fd, struct stat* buf) {
546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->GetStat(buf);
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
5717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error)
573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::fchdir(int fd) {
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedKernelHandle handle;
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string path;
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireHandleAndPath(fd, &handle, &path);
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error) {
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = error;
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!handle->node()->IsaDir()) {
5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = ENOTDIR;
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (path.empty()) {
5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = EBADF;
5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = SetCWD(path);
5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error) {
5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // errno is return value from SetCWD
6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    errno = error;
6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return 0;
6048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
60690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int KernelProxy::ftruncate(int fd, off_t length) {
607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
61390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FTruncate(length);
615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
61990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
62190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
62290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fsync(int fd) {
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)  }
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FSync();
632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::fdatasync(int fd) {
6418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = ENOSYS;
6428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
6438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::isatty(int fd) {
646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
650effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return 0;
651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
653effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  error = handle->node()->Isatty();
654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
656effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return 0;
657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
659effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return 1;
660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::ioctl(int fd, int request, va_list args) {
663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
664bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->node()->VIoctl(request, args);
671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint KernelProxy::futimens(int fd, const struct timespec times[2]) {
6801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedKernelHandle handle;
6811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Error error = AcquireHandle(fd, &handle);
6821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (error) {
6831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    errno = error;
6841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return -1;
6851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  error = handle->node()->Futimens(times);
6881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (error) {
6891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    errno = error;
6901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return -1;
6911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return 0;
6941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
702868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  off_t new_offset;
705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = handle->Seek(offset, whence, &new_offset);
706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return new_offset;
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::unlink(const char* path) {
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
7177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
723868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Unlink(rel);
725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::truncate(const char* path, off_t len) {
7341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int fd = open(path, O_WRONLY, 0);
7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (-1 == fd)
7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return -1;
7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int result = ftruncate(fd, len);
7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  close(fd);
7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return result;
7418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::lstat(const char* path, struct stat* buf) {
7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return stat(path, buf);
7458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int KernelProxy::rename(const char* path, const char* newpath) {
7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
749f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Path rel;
7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
751f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
752f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
753f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
754f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
755f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem newfs;
757f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Path newrel;
7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = AcquireFsAndRelPath(newpath, &newfs, &newrel);
759f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
760f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
761f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
762f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
763f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (newfs.get() != fs.get()) {
765f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Renaming accross mountpoints is not allowed
766f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = EXDEV;
767f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
768f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
769f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
770f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // They already point to the same path
771f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rel == newrel)
772f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return 0;
773f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Rename(rel, newrel);
775f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error) {
776f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = error;
777f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
778f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
779f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
780f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return 0;
7818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
7828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::remove(const char* path) {
7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs;
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
7867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error error = AcquireFsAndRelPath(path, &fs, &rel);
788868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
790868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
791868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = fs->Remove(rel);
794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint KernelProxy::fchmod(int fd, mode_t mode) {
803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Error error = AcquireHandle(fd, &handle);
805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
8101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  error = handle->node()->Fchmod(mode);
8111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (error) {
8121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    errno = error;
8131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return -1;
8141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
8151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int KernelProxy::fcntl(int fd, int request, va_list args) {
8201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Error error = 0;
8211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
822cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // F_GETFD and F_SETFD are descriptor specific flags that
823cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // are stored in the KernelObject's decriptor map unlike
8241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // F_GETFL and F_SETFL which are handle specific.
8251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  switch (request) {
8261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case F_GETFD: {
8271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int rtn = -1;
8281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      error = GetFDFlags(fd, &rtn);
8291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (error) {
8301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        errno = error;
8311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return -1;
8321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
8331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return rtn;
8341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
8351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    case F_SETFD: {
8361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      int flags = va_arg(args, int);
8371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      error = SetFDFlags(fd, flags);
8381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (error) {
8391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        errno = error;
8401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return -1;
8411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
8421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return 0;
8431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
8441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
8451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
84668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedKernelHandle handle;
8471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  error = AcquireHandle(fd, &handle);
84868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (error) {
84968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    errno = error;
85068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
85168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
85268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int rtn = 0;
8544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->VFcntl(request, &rtn, args);
8554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
8564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
8574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
8584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
8594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return rtn;
86168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
86268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::access(const char* path, int amode) {
8641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  struct stat buf;
8651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int rtn = stat(path, &buf);
8661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rtn != 0)
8671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return rtn;
868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
8691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (((amode & R_OK) && !(buf.st_mode & S_IREAD)) ||
8701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ((amode & W_OK) && !(buf.st_mode & S_IWRITE)) ||
8711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ((amode & X_OK) && !(buf.st_mode & S_IEXEC))) {
8721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    errno = EACCES;
873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
874eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
879cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::readlink(const char* path, char* buf, size_t count) {
880116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LOG_TRACE("readlink is not implemented.");
8818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  errno = EINVAL;
8828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return -1;
8838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
8848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint KernelProxy::utimens(const char* path, const struct timespec times[2]) {
8861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int fd = open(path, O_RDONLY, 0);
8871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (-1 == fd)
8881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return -1;
8891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int result = futimens(fd, times);
8911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  close(fd);
8921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return result;
8938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
8948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(noelallen): Needs implementation.
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::link(const char* oldpath, const char* newpath) {
897116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LOG_TRACE("link is not implemented.");
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::symlink(const char* oldpath, const char* newpath) {
903116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LOG_TRACE("symlink is not implemented.");
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void* KernelProxy::mmap(void* addr,
909868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        size_t length,
910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int prot,
911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int flags,
912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int fd,
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        size_t offset) {
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We shouldn't be getting anonymous mmaps here.
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert((flags & MAP_ANONYMOUS) == 0);
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(fd != -1);
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
920868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
921868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MAP_FAILED;
923868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* new_addr;
9267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return MAP_FAILED;
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new_addr;
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::munmap(void* addr, size_t length) {
93690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // NOTE: The comment below is from a previous discarded implementation that
93790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tracks mmap'd regions. For simplicity, we no longer do this; because we
93890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // "snapshot" the contents of the file in mmap(), and don't support
93990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // write-back or updating the mapped region when the file is written, holding
94090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on to the KernelHandle is pointless.
94190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
94290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If we ever do, these threading issues should be considered.
94390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
94490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
94590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // WARNING: this function may be called by free().
94690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
94790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // There is a potential deadlock scenario:
94890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 1: open() -> takes lock1 -> free() -> takes lock2
94990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
95090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
95190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note that open() above could be any function that takes a lock that is
95290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // shared with munmap (this includes munmap!)
95390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
95490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // To prevent this, we avoid taking locks in munmap() that are used by other
95590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // nacl_io functions that may call free. Specifically, we only take the
95690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // mmap_lock, which is only shared with mmap() above. There is still a
95790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // possibility of deadlock if mmap() or munmap() calls free(), so this is not
95890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // allowed.
95990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
96090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unfortunately, munmap still needs to acquire other locks; see the call to
96190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // ReleaseHandle below which takes the process lock. This is safe as long as
96290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // this is never executed from free() -- we can be reasonably sure this is
96390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // true, because malloc only makes anonymous mmap() requests, and should only
96490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // be munmapping those allocations. We never add to mmap_info_list_ for
96590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // anonymous maps, so the unmap_list should always be empty when called from
96690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // free().
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
970bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcflush(int fd, int queue_selector) {
971bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
972bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
973bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
974bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
975bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
976bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
977bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
978bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcflush(queue_selector);
979bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
980bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
981bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
982bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
983bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
984bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
985bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
986bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
987bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
988bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
989bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
990bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
991bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
992bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
993bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
994bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
995bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcgetattr(termios_p);
996bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
997bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
998bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
999bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
1000bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1001bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
1002bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
1003bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1004cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::tcsetattr(int fd,
1005cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           int optional_actions,
1006cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           const struct termios* termios_p) {
1007bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  ScopedKernelHandle handle;
1008bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  Error error = AcquireHandle(fd, &handle);
1009bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
1010bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
1011bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
1012bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
1013bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1014bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  error = handle->node()->Tcsetattr(optional_actions, termios_p);
1015bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (error) {
1016bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    errno = error;
1017bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return -1;
1018bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
1019bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1020bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return 0;
1021bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
1022bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
10233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int KernelProxy::kill(pid_t pid, int sig) {
10243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Currently we don't even pretend that other processes exist
10253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // so we can only send a signal to outselves.  For kill(2)
10263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // pid 0 means the current process group and -1 means all the
10273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // processes we have permission to send signals to.
10283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (pid != getpid() && pid != -1 && pid != 0) {
10293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = ESRCH;
10303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
10313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
10323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Raise an event so that select/poll get interrupted.
103468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AUTO_LOCK(signal_emitter_->GetLock())
103568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  signal_emitter_->RaiseEvents_Locked(POLLERR);
10363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (sig) {
10373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH:
1038f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (sigwinch_handler_.sa_handler != SIG_IGN &&
1039f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          sigwinch_handler_.sa_handler != SIG_DFL) {
1040f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        sigwinch_handler_.sa_handler(SIGWINCH);
1041f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
10423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
10433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR1:
10453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGUSR2:
10463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
10473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    default:
1049116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      LOG_TRACE("Unsupported signal: %d", sig);
10503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EINVAL;
10513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
10523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
10533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
10543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
10553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1056cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::sigaction(int signum,
1057cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           const struct sigaction* action,
1058f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           struct sigaction* oaction) {
1059f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (action && action->sa_flags & SA_SIGINFO) {
1060f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // We don't support SA_SIGINFO (sa_sigaction field) yet
1061f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    errno = EINVAL;
1062f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return -1;
1063f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1064f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (signum) {
10663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Handled signals.
10673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGWINCH: {
1068f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (oaction)
1069f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        *oaction = sigwinch_handler_;
1070f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (action) {
1071f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        sigwinch_handler_ = *action;
1072f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
1073f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return 0;
10743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
10753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Known signals
10773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGHUP:
10783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGINT:
10793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPIPE:
10803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPOLL:
10813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGPROF:
10823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTERM:
10833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGCHLD:
10843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGURG:
10853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGFPE:
10863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGILL:
10873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGQUIT:
10883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGSEGV:
10893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SIGTRAP:
1090f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (action && action->sa_handler != SIG_DFL) {
1091f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // Trying to set this action to anything other than SIG_DFL
1092f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // is not yet supported.
1093116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        LOG_TRACE("sigaction on signal %d != SIG_DFL not supported.", sig);
1094f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        errno = EINVAL;
1095f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return -1;
1096f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
1097f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1098f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (oaction) {
1099f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        memset(oaction, 0, sizeof(*oaction));
1100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        oaction->sa_handler = SIG_DFL;
1101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
1102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return 0;
1103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // KILL and STOP cannot be handled
1105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SIGKILL:
1106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SIGSTOP:
1107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      LOG_TRACE("sigaction on SIGKILL/SIGSTOP not supported.");
1108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      errno = EINVAL;
1109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return -1;
11103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
11113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Unknown signum
11133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  errno = EINVAL;
1114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return -1;
11153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
11163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#ifdef PROVIDES_SOCKET_API
1118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::select(int nfds,
1120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        fd_set* readfds,
1121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        fd_set* writefds,
1122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        fd_set* exceptfds,
1123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        struct timeval* timeout) {
112468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<pollfd> pollfds;
112568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
112668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int fd = 0; fd < nfds; fd++) {
11273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    int events = 0;
1128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (readfds && FD_ISSET(fd, readfds)) {
11293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLIN;
1130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FD_CLR(fd, readfds);
1131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
11323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (writefds && FD_ISSET(fd, writefds)) {
11343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLOUT;
1135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FD_CLR(fd, writefds);
1136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
11373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (exceptfds && FD_ISSET(fd, exceptfds)) {
11393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      events |= POLLERR | POLLHUP;
1140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FD_CLR(fd, exceptfds);
1141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
11423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
114368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events) {
114468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfd info;
114568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.fd = fd;
114668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info.events = events;
114768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pollfds.push_back(info);
11483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
114968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
11503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
115168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // NULL timeout signals wait forever.
115268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int ms_timeout = -1;
115368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (timeout != NULL) {
115468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000);
11553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
115668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // If the timeout is invalid or too long (larger than signed 32 bit).
115768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
1158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || (ms < 0) ||
1159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        (ms >= INT_MAX)) {
1160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      LOG_TRACE("Invalid timeout: tv_sec=%d tv_usec=%d.",
1161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                timeout->tv_sec,
1162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                timeout->tv_usec);
116368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = EINVAL;
116468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return -1;
11653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
11663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
116768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ms_timeout = static_cast<int>(ms);
11683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
11693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
117068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int result = poll(&pollfds[0], pollfds.size(), ms_timeout);
117168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result == -1)
117268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return -1;
11733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
117468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int event_cnt = 0;
117568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t index = 0; index < pollfds.size(); index++) {
117668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pollfd* info = &pollfds[index];
117768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLIN) {
117868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, readfds);
117968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
11803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
118168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & POLLOUT) {
118268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, writefds);
118368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
11843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
118568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->revents & (POLLHUP | POLLERR)) {
118668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FD_SET(info->fd, exceptfds);
118768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      event_cnt++;
11883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
11893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
11903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
119168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return event_cnt;
119268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
119468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)struct PollInfo {
119568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PollInfo() : index(-1) {};
11963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
119768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<struct pollfd*> fds;
119868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int index;
119968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
12003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
120168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)typedef std::map<EventEmitter*, PollInfo> EventPollMap_t;
12023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::poll(struct pollfd* fds, nfds_t nfds, int timeout) {
120468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EventPollMap_t event_map;
12053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
120668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<EventRequest> requests;
12073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  size_t event_cnt = 0;
120868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
120968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int index = 0; static_cast<nfds_t>(index) < nfds; index++) {
12103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    ScopedKernelHandle handle;
121168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    struct pollfd* fd_info = &fds[index];
121268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = AcquireHandle(fd_info->fd, &handle);
121368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
121468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    fd_info->revents = 0;
12153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
12163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If the node isn't open, or somehow invalid, mark it so.
12173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (err != 0) {
121868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
12193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
12203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
12213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
12223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
12233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // If it's already signaled, then just capture the event
122468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ScopedEventEmitter emitter(handle->node()->GetEventEmitter());
122568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int events = POLLIN | POLLOUT;
122668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (emitter)
122768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      events = emitter->GetEventStatus();
122868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
122968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (events & fd_info->events) {
123068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = events & fd_info->events;
12313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
12323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
12333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
12343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
123568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (NULL == emitter) {
123668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      fd_info->revents = POLLNVAL;
12373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      event_cnt++;
12383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      continue;
12393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
124068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
124168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Otherwise try to track it.
124268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    PollInfo* info = &event_map[emitter.get()];
124368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (info->index == -1) {
124468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest request;
124568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.emitter = emitter;
124668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.filter = fd_info->events;
124768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      request.events = 0;
124868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
124968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      info->index = requests.size();
125068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      requests.push_back(request);
125168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
125268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    info->fds.push_back(fd_info);
125368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    requests[info->index].filter |= fd_info->events;
12543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
12553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
125668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If nothing is signaled, then we must wait on the event map
12573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (0 == event_cnt) {
125868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EventListenerPoll wait;
125968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Error err = wait.WaitOnAny(&requests[0], requests.size(), timeout);
126068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if ((err != 0) && (err != ETIMEDOUT)) {
126168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      errno = err;
12623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
12633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
126468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
126568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (size_t rindex = 0; rindex < requests.size(); rindex++) {
126668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EventRequest* request = &requests[rindex];
126768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (request->events) {
126868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        PollInfo* poll_info = &event_map[request->emitter.get()];
126968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        for (size_t findex = 0; findex < poll_info->fds.size(); findex++) {
127068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          struct pollfd* fd_info = poll_info->fds[findex];
127168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          uint32_t events = fd_info->events & request->events;
127268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          if (events) {
127368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            fd_info->revents = events;
127468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            event_cnt++;
127568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          }
127668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
127768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
127868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
12793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
12803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
12813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return event_cnt;
12823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
12833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Socket Functions
1285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
1286a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
12924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
12934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
12944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
12964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
12984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PP_Resource new_sock = 0;
12994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Accept(&new_sock, addr, len);
13004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
13014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
13024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
13034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
13044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SocketNode* sock = new TcpNode(stream_fs_.get(), new_sock);
13064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
13075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The SocketNode now holds a reference to the new socket
13084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // so we release ours.
13094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ppapi_->ReleaseResource(new_sock);
1310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error = sock->Init(O_RDWR);
13114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
13124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
13134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
13144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
13154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
13165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node(sock);
1317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedKernelHandle new_handle(new KernelHandle(stream_fs_, node));
1318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error = new_handle->Init(O_RDWR);
13191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (error != 0) {
13201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    errno = error;
13211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return -1;
13221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
13231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
13244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AllocateFD(new_handle);
1325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
1328a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Bind(addr, len);
13383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
13393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
13403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1345a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
1347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
13534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
13544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
13554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
13574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
13594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Connect(addr, len);
13604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
13614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
13623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
13633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
13643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
13653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void KernelProxy::freeaddrinfo(struct addrinfo* res) {
13695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return host_resolver_.freeaddrinfo(res);
13705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
13715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int KernelProxy::getaddrinfo(const char* node,
1373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             const char* service,
13745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const struct addrinfo* hints,
13755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             struct addrinfo** res) {
13765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return host_resolver_.getaddrinfo(node, service, hints, res);
13775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
13785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint KernelProxy::getnameinfo(const struct sockaddr *sa,
13801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             socklen_t salen,
13811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             char *host,
13821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             size_t hostlen,
13831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             char *serv,
13841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             size_t servlen,
13851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             int flags) {
13861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return host_resolver_.getnameinfo(sa, salen, host, hostlen, serv, servlen,
13871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    flags);
13881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
13891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1390bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochstruct hostent* KernelProxy::gethostbyname(const char* name) {
1391bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return host_resolver_.gethostbyname(name);
1392bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
1393bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1394a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
1395a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1398a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1399a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1400a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1403a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetPeerName(addr, len);
14053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
14063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
14073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
14083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
1414a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr || NULL == len) {
1415a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1416a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1419a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1421a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->GetSockName(addr, len);
14243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
14253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
14263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
14273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::getsockopt(int fd,
14334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int lvl,
14344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int optname,
14354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            void* optval,
14364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            socklen_t* len) {
1437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval || NULL == len) {
1438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
14474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
14484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
14494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
14504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
14514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
14524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1454a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::listen(int fd, int backlog) {
1456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->Listen(backlog);
14614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
14624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
14634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
14644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
14654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
14664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1467a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ssize_t KernelProxy::recv(int fd, void* buf, size_t len, int flags) {
1470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1475a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
14764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
14774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
14784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1479a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
14804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1481a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
14834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Recv(buf, len, flags, &out_len);
14844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
14854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
14863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
14873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
14883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
14893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1490a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1491a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1492a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvfrom(int fd,
1493a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              void* buf,
1494a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              size_t len,
1495a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              int flags,
1496a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              struct sockaddr* addr,
1497a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                              socklen_t* addrlen) {
1498a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, recvfrom with a null addr is identical to recv.
1499a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1500a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return recv(fd, buf, len, flags);
1501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf || NULL == addrlen) {
1504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
15094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
15104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
15114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
15134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
15164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
15174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
15184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
15193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
15203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
15213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1523a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1524a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1525a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (NULL == msg) {
1527a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1528a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1529a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1530a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1531a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1532a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1535a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1536a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1537a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1538a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1539a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1542a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1543a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1544a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1545a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
15464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
15474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
15484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1549a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
15504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1551a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
15534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->Send(buf, len, flags, &out_len);
15544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
15554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
15563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
15573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
15583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1560a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1561a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1562a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendto(int fd,
1563a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* buf,
1564a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            size_t len,
1565a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int flags,
1566a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const struct sockaddr* addr,
1567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t addrlen) {
1568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // According to the manpage, sendto with a null addr is identical to send.
1569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == addr) {
1570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return send(fd, buf, len, flags);
1571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == buf) {
1574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
15794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
15804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error) {
15814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
1582a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
15834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
15853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int out_len = 0;
15864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len);
15874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (error != 0) {
15884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = error;
15893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
15903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
15913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<ssize_t>(out_len);
1593a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1595a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
1596a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == msg) {
1597a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1598a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1599a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1600a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1601a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1602a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1603a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1604a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1605a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = EOPNOTSUPP;
1606a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1607a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1608a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1609a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::setsockopt(int fd,
1610a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int lvl,
1611a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            int optname,
1612a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const void* optval,
1613a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            socklen_t len) {
1614a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == optval) {
1615a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1616a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1617a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1618a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1619a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1620a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1621a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1622a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
16234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
16244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
16254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = err;
16264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
16274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
16284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
16294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
1630a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1631a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1632a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::shutdown(int fd, int how) {
1633a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedKernelHandle handle;
1634a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AcquireSocketHandle(fd, &handle) == -1)
1635a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1636a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
16373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Error err = handle->socket_node()->Shutdown(how);
16383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err != 0) {
16393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    errno = err;
16403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return -1;
16413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
16423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
16433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
1644a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1645a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1646a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socket(int domain, int type, int protocol) {
1647a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1648a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1649a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1650a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1651a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int open_flags = O_RDWR;
1653f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1654f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (type & SOCK_CLOEXEC) {
1655f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#ifdef O_CLOEXEC
1656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // The NaCl newlib version of fcntl.h doesn't currently define
1657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // O_CLOEXEC.
1658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO(sbc): remove this guard once it gets added.
1659f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    open_flags |= O_CLOEXEC;
1660f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
1661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    type &= ~SOCK_CLOEXEC;
1662f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1663f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (type & SOCK_NONBLOCK) {
1665f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    open_flags |= O_NONBLOCK;
1666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    type &= ~SOCK_NONBLOCK;
1667f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
16695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode* sock = NULL;
16703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (type) {
16713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_DGRAM:
1672cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      sock = new UdpNode(stream_fs_.get());
16733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
16743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
16753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case SOCK_STREAM:
1676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      sock = new TcpNode(stream_fs_.get());
16773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
16783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1679f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_SEQPACKET:
1680f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_RDM:
1681f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case SOCK_RAW:
16823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      errno = EPROTONOSUPPORT;
16833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return -1;
1684f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1685f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    default:
1686f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      errno = EINVAL;
1687f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return -1;
1688a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1689a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
16905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node(sock);
1691f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Error rtn = sock->Init(O_RDWR);
16924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (rtn != 0) {
16934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    errno = rtn;
16944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return -1;
16953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
16963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1697cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScopedKernelHandle handle(new KernelHandle(stream_fs_, node));
1698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  rtn = handle->Init(open_flags);
16991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (rtn != 0) {
17001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    errno = rtn;
17011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return -1;
17021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
17031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
17044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AllocateFD(handle);
1705a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1706a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1707a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1708a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (NULL == sv) {
1709a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EFAULT;
1710a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1711a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1712a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1713a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1714a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // socket pairs. Thus, this function always fails.
1715a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_UNIX != domain) {
1716a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EPROTONOSUPPORT;
1717a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1718a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1719a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1720a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (AF_INET != domain && AF_INET6 != domain) {
1721a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = EAFNOSUPPORT;
1722a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1723a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1724a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1725a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // We cannot reach this point.
1726a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  errno = ENOSYS;
1727a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return -1;
1728a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1729a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1730a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1731a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Error error = AcquireHandle(fd, handle);
1732a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1733a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (error) {
1734a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = error;
1735a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1736a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1737a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1738a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1739a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    errno = ENOTSOCK;
1740a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return -1;
1741a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1742a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1743a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return 0;
1744a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
1745a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1746bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif  // PROVIDES_SOCKET_API
1747a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1748bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}  // namespace_nacl_io
1749