kernel_proxy.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "utils/auto_lock.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "utils/ref_object.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef MAXPATHLEN
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAXPATHLEN 256
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(noelallen) : Grab/Redefine these in the kernel object once available.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define USR_ID 1002
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define GRP_ID 1003
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KernelProxy::KernelProxy()
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   : dev_(0),
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     ppapi_(NULL) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KernelProxy::~KernelProxy() {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete ppapi_;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KernelProxy::Init(PepperInterface* ppapi) {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi_ = ppapi;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cwd_ = "/";
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dev_ = 1;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  factories_["memfs"] = MountMem::Create<MountMem>;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  factories_["dev"] = MountDev::Create<MountDev>;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  factories_["html5fs"] = MountHtml5Fs::Create<MountHtml5Fs>;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  factories_["httpfs"] = MountHttp::Create<MountHttp>;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  factories_["passthroughfs"] = MountPassthrough::Create<MountPassthrough>;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create passthrough mount at root
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringMap_t smap;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mounts_["/"] = MountPassthrough::Create<MountPassthrough>(
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dev_++, smap, ppapi_);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mounts_["/dev"] = MountDev::Create<MountDev>(dev_++, smap, ppapi_);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open the first three in order to get STDIN, STDOUT, STDERR
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  open("/dev/stdin", O_RDONLY);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  open("/dev/stdout", O_WRONLY);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  open("/dev/stderr", O_WRONLY);
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::open(const char *path, int oflags) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Mount* mnt = AcquireMountAndPath(path, &rel);
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mnt == NULL) return -1;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MountNode* node = mnt->Open(rel, oflags);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (node == NULL) {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ReleaseMount(mnt);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = new KernelHandle(mnt, node, oflags);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = AllocateFD(handle);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mnt->AcquireNode(node);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseMount(mnt);
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fd;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::close(int fd) {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = AcquireHandle(fd);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == handle) return -1;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Mount* mount = handle->mount_;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Acquire the mount to ensure FreeFD doesn't prematurely destroy it.
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mount->Acquire();
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // FreeFD will release the handle/mount held by this fd.
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeFD(fd);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If this handle is the last reference to its node, releasing it will close
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the node.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Finally, release the mount.
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mount->Release();
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup(int oldfd) {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = AcquireHandle(oldfd);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == handle) return -1;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int newfd = AllocateFD(handle);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::dup2(int oldfd, int newfd) {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If it's the same file handle, just return
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (oldfd == newfd) return newfd;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* old_handle = AcquireHandle(oldfd);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == old_handle) return -1;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeAndReassignFD(newfd, old_handle);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(old_handle);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return newfd;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getcwd(char* buf, size_t size) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AutoLock lock(&process_lock_);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size <= 0) {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EINVAL;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If size is 0, allocate as much as we need.
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size == 0) {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size = cwd_.size() + 1;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify the buffer is large enough
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (size <= cwd_.size()) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ERANGE;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Allocate the buffer if needed
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (buf == NULL) {
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buf = static_cast<char*>(malloc(size));
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  strcpy(buf, cwd_.c_str());
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return buf;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)char* KernelProxy::getwd(char* buf) {
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == buf) {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EFAULT;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return getcwd(buf, MAXPATHLEN);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::chmod(const char *path, mode_t mode) {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = KernelProxy::open(path, O_RDWR);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (-1 == fd) return -1;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int ret = fchmod(fd, mode);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ret;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::mkdir(const char *path, mode_t mode) {
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Mount* mnt = AcquireMountAndPath(path, &rel);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mnt == NULL) return -1;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int val = mnt->Mkdir(rel, mode);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseMount(mnt);
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return val;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::rmdir(const char *path) {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Mount* mnt = AcquireMountAndPath(path, &rel);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mnt == NULL) return -1;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int val = mnt->Rmdir(rel);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseMount(mnt);
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return val;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::stat(const char *path, struct stat *buf) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = open(path, O_RDONLY);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (-1 == fd) return -1;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int ret = fstat(fd, buf);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  close(fd);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ret;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::chdir(const char* path) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct stat statbuf;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (stat(path, &statbuf) == -1)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_dir = (statbuf.st_mode & S_IFDIR) != 0;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_dir) {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AutoLock lock(&process_lock_);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cwd_ = GetAbsPathLocked(path).Join();
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = ENOTDIR;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::mount(const char *source, const char *target,
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const char *filesystemtype, unsigned long mountflags,
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const void *data) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // See if it's already mounted
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string abs_targ;
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Scope this lock to prevent holding both process and kernel locks
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AutoLock lock(&process_lock_);
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    abs_targ = GetAbsPathLocked(target).Join();
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AutoLock lock(&kernel_lock_);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mounts_.find(abs_targ) != mounts_.end()) {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EBUSY;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Find a factory of that type
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MountFactoryMap_t::iterator factory = factories_.find(filesystemtype);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (factory == factories_.end()) {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = ENODEV;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StringMap_t smap;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  smap["SOURCE"] = source;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  smap["TARGET"] = abs_targ;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (data) {
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    char* str = strdup(static_cast<const char *>(data));
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    char* ptr = strtok(str,",");
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    char* val;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (ptr != NULL) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      val = strchr(ptr, '=');
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (val) {
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *val = 0;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        smap[ptr] = val + 1;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        smap[ptr] = "TRUE";
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ptr = strtok(NULL, ",");
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    free(str);
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Mount* mnt = factory->second(dev_++, smap, ppapi_);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mnt) {
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mounts_[abs_targ] = mnt;
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::umount(const char *path) {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path abs_path;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Scope this lock to prevent holding both process and kernel locks
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AutoLock lock(&process_lock_);
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    abs_path = GetAbsPathLocked(path);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AutoLock lock(&kernel_lock_);
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MountMap_t::iterator it = mounts_.find(abs_path.Join());
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mounts_.end() == it) {
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EINVAL;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it->second->RefCount() != 1) {
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EBUSY;
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  it->second->Release();
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mounts_.erase(it);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ssize_t KernelProxy::read(int fd, void *buf, size_t nbytes) {
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = AcquireHandle(fd);
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // check if fd is valid and handle exists
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == handle) return -1;
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AutoLock lock(&handle->lock_);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ssize_t cnt = handle->node_->Read(handle->offs_, buf, nbytes);
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cnt > 0) handle->offs_ += cnt;
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ssize_t KernelProxy::write(int fd, const void *buf, size_t nbytes) {
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = AcquireHandle(fd);
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // check if fd is valid and handle exists
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == handle) return -1;
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AutoLock lock(&handle->lock_);
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ssize_t cnt = handle->node_->Write(handle->offs_, buf, nbytes);
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cnt > 0) handle->offs_ += cnt;
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fstat(int fd, struct stat* buf) {
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = AcquireHandle(fd);
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // check if fd is valid and handle exists
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == handle) return -1;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int ret = handle->node_->GetStat(buf);
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ret;
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = AcquireHandle(fd);
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // check if fd is valid and handle exists
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == handle) return -1;
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AutoLock lock(&handle->lock_);
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int cnt = handle->node_->GetDents(handle->offs_,
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<dirent *>(buf), count);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cnt > 0) handle->offs_ += cnt;
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cnt;
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fsync(int fd) {
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = AcquireHandle(fd);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // check if fd is valid and handle exists
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == handle) return -1;
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int ret = handle->node_->FSync();
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ret;
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::isatty(int fd) {
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = AcquireHandle(fd);
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // check if fd is valid and handle exists
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == handle) return -1;
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int ret = handle->node_->IsaTTY();
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ret;
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = AcquireHandle(fd);
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // check if fd is valid and handle exists
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == handle) return -1;
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AutoLock lock(&handle->lock_);
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int ret = handle->Seek(offset, whence);
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ret;
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::unlink(const char* path) {
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Mount* mnt = AcquireMountAndPath(path, &rel);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mnt == NULL) return -1;
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int val = mnt->Unlink(rel);
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseMount(mnt);
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return val;
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::remove(const char* path) {
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Mount* mnt = AcquireMountAndPath(path, &rel);
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mnt == NULL) return -1;
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int val = mnt->Remove(rel);
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseMount(mnt);
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return val;
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(noelallen): Needs implementation.
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::fchmod(int fd, int mode) {
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::access(const char* path, int amode) {
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::link(const char* oldpath, const char* newpath) {
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::symlink(const char* oldpath, const char* newpath) {
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  errno = EINVAL;
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return -1;
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void* KernelProxy::mmap(void* addr, size_t length, int prot, int flags, int fd,
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        size_t offset) {
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We shouldn't be getting anonymous mmaps here.
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert((flags & MAP_ANONYMOUS) == 0);
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(fd != -1);
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = AcquireHandle(fd);
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NULL == handle)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MAP_FAILED;
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* new_addr;
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AutoLock lock(&handle->lock_);
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    new_addr = handle->node_->MMap(addr, length, prot, flags, offset);
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (new_addr == MAP_FAILED) {
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ReleaseHandle(handle);
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MAP_FAILED;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't release the KernelHandle, it is now owned by the MMapInfo.
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AutoLock lock(&process_lock_);
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mmap_info_list_.push_back(MMapInfo(new_addr, length, handle));
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new_addr;
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::munmap(void* addr, size_t length) {
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (addr == NULL || length == 0) {
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    errno = EINVAL;
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return -1;
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MMapInfoList_t unmap_list;
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AutoLock lock(&process_lock_);
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int mmap_list_end = mmap_info_list_.size();
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void* addr_end = static_cast<char*>(addr) + length;
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = 0; i < mmap_list_end;) {
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const MMapInfo& mmap_info = mmap_info_list_[i];
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (addr < static_cast<char*>(mmap_info.addr) + mmap_info.length &&
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          mmap_info.addr < addr_end)
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // This memory area should be unmapped; swap it with the last entry in
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // our list.
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::swap(mmap_info_list_[i], mmap_info_list_[--mmap_list_end]);
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ++i;
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int num_to_unmap =- mmap_info_list_.size() - mmap_list_end;
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!num_to_unmap) {
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // From the Linux mmap man page: "It is not an error if the indicated
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // range does not contain any mapped pages."
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::copy(mmap_info_list_.begin() + mmap_list_end, mmap_info_list_.end(),
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              std::back_inserter(unmap_list));
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mmap_info_list_.resize(mmap_list_end);
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Unmap everything past the new end of the list.
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < unmap_list.size(); ++i) {
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const MMapInfo& mmap_info = unmap_list[i];
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    KernelHandle* handle = mmap_info.handle;
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    assert(handle != NULL);
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Ignore the results from individual munmaps.
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    handle->node_->Munmap(mmap_info.addr, mmap_info.length);
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ReleaseHandle(handle);
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int KernelProxy::open_resource(const char* path) {
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Path rel;
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Mount* mnt = AcquireMountAndPath(path, &rel);
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mnt == NULL) return -1;
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MountNode* node = mnt->OpenResource(rel);
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (node == NULL) {
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    node = mnt->Open(rel, O_RDONLY);
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (node == NULL) {
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ReleaseMount(mnt);
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return -1;
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // OpenResource failed, try Open().
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  KernelHandle* handle = new KernelHandle(mnt, node, O_RDONLY);
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int fd = AllocateFD(handle);
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mnt->AcquireNode(node);
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseHandle(handle);
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseMount(mnt);
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fd;
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
545