kernel_proxy.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
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>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <pthread.h>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string.h>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <iterator>
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_wrap_real.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_dev.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_html5fs.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_http.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_mem.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_node.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_passthrough.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osmman.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osstat.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/path.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/pepper_interface.h"
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "nacl_io/typed_mount_factory.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/auto_lock.h"
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/ref_object.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef MAXPATHLEN
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAXPATHLEN 256
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(noelallen) : Grab/Redefine these in the kernel object once available.
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define USR_ID 1002
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define GRP_ID 1003
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochKernelProxy::KernelProxy() : dev_(0), ppapi_(NULL) {
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochKernelProxy::~KernelProxy() {
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Clean up the MountFactories.
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (MountFactoryMap_t::iterator i = factories_.begin();
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       i != factories_.end();
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       ++i) {
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    delete i->second;
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  delete ppapi_;
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KernelProxy::Init(PepperInterface* ppapi) {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi_ = ppapi;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dev_ = 1;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["memfs"] = new TypedMountFactory<MountMem>;
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["dev"] = new TypedMountFactory<MountDev>;
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>;
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["httpfs"] = new TypedMountFactory<MountHttp>;
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result;
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = mount("", "/", "passthroughfs", 0, NULL);
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  assert(result == 0);
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = mount("", "/dev", "dev", 0, NULL);
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  assert(result == 0);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open the first three in order to get STDIN, STDOUT, STDERR
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  open("/dev/stdin", O_RDONLY);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  open("/dev/stdout", O_WRONLY);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  open("/dev/stderr", O_WRONLY);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::open_resource(const char* path) {
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMountNode node;
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = mnt->OpenResource(rel, &node);
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // OpenResource failed, try Open().
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    error = mnt->Open(rel, O_RDONLY, &node);
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (error) {
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      errno = error;
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return -1;
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedKernelHandle handle(new KernelHandle(mnt, node));
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Init(O_RDONLY);
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return AllocateFD(handle);
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::open(const char* path, int oflags) {
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMountNode node;
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndNode(path, oflags, &mnt, &node);
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle(new KernelHandle(mnt, node));
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = handle->Init(oflags);
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return AllocateFD(handle);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::close(int fd) {
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Remove the FD from the process open file descriptor map
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeFD(fd);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup(int oldfd) {
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(oldfd, &handle);
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return AllocateFD(handle);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup2(int oldfd, int newfd) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If it's the same file handle, just return
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (oldfd == newfd)
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return newfd;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle old_handle;
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(oldfd, &old_handle);
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeAndReassignFD(newfd, old_handle);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint KernelProxy::chdir(const char* path) {
1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = SetCWD(path);
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return 0;
1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getcwd(char* buf, size_t size) {
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string cwd = GetCWD();
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size <= 0) {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EINVAL;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If size is 0, allocate as much as we need.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size == 0) {
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size = cwd.size() + 1;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify the buffer is large enough
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (size <= cwd.size()) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ERANGE;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Allocate the buffer if needed
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (buf == NULL) {
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buf = static_cast<char*>(malloc(size));
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  strcpy(buf, cwd.c_str());
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buf;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getwd(char* buf) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == buf) {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EFAULT;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return getcwd(buf, MAXPATHLEN);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::chmod(const char* path, mode_t mode) {
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int fd = KernelProxy::open(path, O_RDONLY);
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fchmod(fd, mode);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::utime(const char* filename, const struct utimbuf* times) {
236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mkdir(const char* path, mode_t mode) {
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Mkdir(rel, mode);
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::rmdir(const char* path) {
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Rmdir(rel);
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::stat(const char* path, struct stat* buf) {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = open(path, O_RDONLY);
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (-1 == fd)
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = fstat(fd, buf);
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::mount(const char* source,
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* target,
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const char* filesystemtype,
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       unsigned long mountflags,
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       const void* data) {
2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string abs_path = GetAbsParts(target).Join();
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find a factory of that type
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MountFactoryMap_t::iterator factory = factories_.find(filesystemtype);
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (factory == factories_.end()) {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ENODEV;
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Create a map of settings
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringMap_t smap;
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  smap["SOURCE"] = source;
3057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  smap["TARGET"] = abs_path;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (data) {
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    char* str = strdup(static_cast<const char*>(data));
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    char* ptr = strtok(str, ",");
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    char* val;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (ptr != NULL) {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      val = strchr(ptr, '=');
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (val) {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *val = 0;
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        smap[ptr] = val + 1;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        smap[ptr] = "TRUE";
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ptr = strtok(NULL, ",");
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    free(str);
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = factory->second->CreateMount(dev_++, smap, ppapi_, &mnt);
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return -1;
3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = AttachMountAtPath(mnt, abs_path);
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int KernelProxy::umount(const char* path) {
3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = DetachMountAtPath(path);
3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (error) {
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    errno = error;
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
3587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Read(buf, nbytes, &cnt);
359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->Write(buf, nbytes, &cnt);
377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fstat(int fd, struct stat* buf) {
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->GetStat(buf);
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int cnt = 0;
4117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error)
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int KernelProxy::ftruncate(int fd, off_t length) {
419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FTruncate(length);
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fsync(int fd) {
436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->FSync();
444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::isatty(int fd) {
453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->IsaTTY();
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint KernelProxy::ioctl(int d, int request, char* argp) {
470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Error error = AcquireHandle(d, &handle);
472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->Ioctl(request, argp);
478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  off_t new_offset;
495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = handle->Seek(offset, whence, &new_offset);
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return new_offset;
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::unlink(const char* path) {
505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
5077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Unlink(rel);
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::remove(const char* path) {
524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedMount mnt;
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
5267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  error = mnt->Remove(rel);
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(noelallen): Needs implementation.
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fchmod(int fd, int mode) {
544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Error error = AcquireHandle(fd, &handle);
546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::access(const char* path, int amode) {
5557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedMount mnt;
556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Path rel;
557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  error = mnt->Access(rel, amode);
565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return -1;
568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return 0;
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(noelallen): Needs implementation.
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::link(const char* oldpath, const char* newpath) {
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::symlink(const char* oldpath, const char* newpath) {
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void* KernelProxy::mmap(void* addr,
584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        size_t length,
585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int prot,
586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int flags,
587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        int fd,
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        size_t offset) {
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We shouldn't be getting anonymous mmaps here.
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert((flags & MAP_ANONYMOUS) == 0);
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(fd != -1);
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedKernelHandle handle;
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = AcquireHandle(fd, &handle);
595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error) {
596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    errno = error;
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MAP_FAILED;
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* new_addr;
6017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (error) {
603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    errno = error;
604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return MAP_FAILED;
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new_addr;
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::munmap(void* addr, size_t length) {
61190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // NOTE: The comment below is from a previous discarded implementation that
61290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tracks mmap'd regions. For simplicity, we no longer do this; because we
61390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // "snapshot" the contents of the file in mmap(), and don't support
61490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // write-back or updating the mapped region when the file is written, holding
61590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on to the KernelHandle is pointless.
61690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
61790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If we ever do, these threading issues should be considered.
61890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
61990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
62090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // WARNING: this function may be called by free().
62190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
62290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // There is a potential deadlock scenario:
62390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 1: open() -> takes lock1 -> free() -> takes lock2
62490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
62590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
62690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note that open() above could be any function that takes a lock that is
62790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // shared with munmap (this includes munmap!)
62890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
62990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // To prevent this, we avoid taking locks in munmap() that are used by other
63090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // nacl_io functions that may call free. Specifically, we only take the
63190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // mmap_lock, which is only shared with mmap() above. There is still a
63290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // possibility of deadlock if mmap() or munmap() calls free(), so this is not
63390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // allowed.
63490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
63590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unfortunately, munmap still needs to acquire other locks; see the call to
63690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // ReleaseHandle below which takes the process lock. This is safe as long as
63790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // this is never executed from free() -- we can be reasonably sure this is
63890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // true, because malloc only makes anonymous mmap() requests, and should only
63990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // be munmapping those allocations. We never add to mmap_info_list_ for
64090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // anonymous maps, so the unmap_list should always be empty when called from
64190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // free().
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
645