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