1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "nacl_io/mount_node.h" 6 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <poll.h> 10 #include <string.h> 11 #include <sys/stat.h> 12 13 #include <algorithm> 14 #include <string> 15 16 #include "nacl_io/kernel_wrap_real.h" 17 #include "nacl_io/mount.h" 18 #include "nacl_io/osmman.h" 19 #include "sdk_util/auto_lock.h" 20 21 namespace nacl_io { 22 23 static const int USR_ID = 1001; 24 static const int GRP_ID = 1002; 25 26 MountNode::MountNode(Mount* mount) : mount_(mount) { 27 memset(&stat_, 0, sizeof(stat_)); 28 stat_.st_gid = GRP_ID; 29 stat_.st_uid = USR_ID; 30 31 // Mount should normally never be NULL, but may be null in tests. 32 // If NULL, at least set the inode to a valid (nonzero) value. 33 if (mount_) 34 mount_->OnNodeCreated(this); 35 else 36 stat_.st_ino = 1; 37 } 38 39 MountNode::~MountNode() {} 40 41 Error MountNode::Init(int perm) { 42 stat_.st_mode |= perm; 43 return 0; 44 } 45 46 void MountNode::Destroy() { 47 if (mount_) { 48 mount_->OnNodeDestroyed(this); 49 } 50 } 51 52 // Declared in EventEmitter, default to regular files which always return 53 // a ready of TRUE for read, write, or error. 54 uint32_t MountNode::GetEventStatus() { 55 uint32_t val = POLLIN | POLLOUT | POLLERR; 56 return val; 57 } 58 59 60 Error MountNode::FSync() { return 0; } 61 62 Error MountNode::FTruncate(off_t length) { return EINVAL; } 63 64 Error MountNode::GetDents(size_t offs, 65 struct dirent* pdir, 66 size_t count, 67 int* out_bytes) { 68 *out_bytes = 0; 69 return ENOTDIR; 70 } 71 72 Error MountNode::GetStat(struct stat* pstat) { 73 AUTO_LOCK(node_lock_); 74 memcpy(pstat, &stat_, sizeof(stat_)); 75 return 0; 76 } 77 78 Error MountNode::Ioctl(int request, char* arg) { return EINVAL; } 79 80 Error MountNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) { 81 *out_bytes = 0; 82 return EINVAL; 83 } 84 85 Error MountNode::Write(size_t offs, 86 const void* buf, 87 size_t count, 88 int* out_bytes) { 89 *out_bytes = 0; 90 return EINVAL; 91 } 92 93 Error MountNode::MMap(void* addr, 94 size_t length, 95 int prot, 96 int flags, 97 size_t offset, 98 void** out_addr) { 99 *out_addr = NULL; 100 101 // Never allow mmap'ing PROT_EXEC. The passthrough node supports this, but we 102 // don't. Fortunately, glibc will fallback if this fails, so dlopen will 103 // continue to work. 104 if (prot & PROT_EXEC) 105 return EPERM; 106 107 // This default mmap support is just enough to make dlopen work. 108 // This implementation just reads from the mount into the mmap'd memory area. 109 void* new_addr = addr; 110 int mmap_error = _real_mmap( 111 &new_addr, length, prot | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0); 112 if (new_addr == MAP_FAILED) { 113 _real_munmap(new_addr, length); 114 return mmap_error; 115 } 116 117 int bytes_read; 118 Error read_error = Read(offset, new_addr, length, &bytes_read); 119 if (read_error) { 120 _real_munmap(new_addr, length); 121 return read_error; 122 } 123 124 *out_addr = new_addr; 125 return 0; 126 } 127 128 Error MountNode::Tcflush(int queue_selector) { 129 return EINVAL; 130 } 131 132 Error MountNode::Tcgetattr(struct termios* termios_p) { 133 return EINVAL; 134 } 135 136 Error MountNode::Tcsetattr(int optional_actions, 137 const struct termios *termios_p) { 138 return EINVAL; 139 } 140 141 int MountNode::GetLinks() { return stat_.st_nlink; } 142 143 int MountNode::GetMode() { return stat_.st_mode & ~S_IFMT; } 144 145 Error MountNode::GetSize(size_t* out_size) { 146 *out_size = stat_.st_size; 147 return 0; 148 } 149 150 int MountNode::GetType() { return stat_.st_mode & S_IFMT; } 151 152 bool MountNode::IsaDir() { return (stat_.st_mode & S_IFDIR) != 0; } 153 154 bool MountNode::IsaFile() { return (stat_.st_mode & S_IFREG) != 0; } 155 156 bool MountNode::IsaTTY() { return (stat_.st_mode & S_IFCHR) != 0; } 157 158 Error MountNode::AddChild(const std::string& name, 159 const ScopedMountNode& node) { 160 return ENOTDIR; 161 } 162 163 Error MountNode::RemoveChild(const std::string& name) { return ENOTDIR; } 164 165 Error MountNode::FindChild(const std::string& name, ScopedMountNode* out_node) { 166 out_node->reset(NULL); 167 return ENOTDIR; 168 } 169 170 int MountNode::ChildCount() { return 0; } 171 172 void MountNode::Link() { stat_.st_nlink++; } 173 174 void MountNode::Unlink() { stat_.st_nlink--; } 175 176 } // namespace nacl_io 177 178