Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 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 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 5 | #include "nacl_io/mount_node.h" |
| 6 | |
| 7 | #include <errno.h> |
| 8 | #include <fcntl.h> |
Ben Murdoch | 3240926 | 2013-08-07 11:04:47 +0100 | [diff] [blame] | 9 | #include <poll.h> |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 10 | #include <string.h> |
| 11 | #include <sys/stat.h> |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 12 | |
| 13 | #include <algorithm> |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 14 | #include <string> |
| 15 | |
| 16 | #include "nacl_io/kernel_wrap_real.h" |
| 17 | #include "nacl_io/mount.h" |
| 18 | #include "nacl_io/osmman.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 19 | #include "sdk_util/auto_lock.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 20 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 21 | namespace nacl_io { |
| 22 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 23 | static const int USR_ID = 1001; |
| 24 | static const int GRP_ID = 1002; |
| 25 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 26 | MountNode::MountNode(Mount* mount) : mount_(mount) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 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. |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 32 | // If NULL, at least set the inode to a valid (nonzero) value. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 33 | if (mount_) |
| 34 | mount_->OnNodeCreated(this); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 35 | else |
| 36 | stat_.st_ino = 1; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 37 | } |
| 38 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 39 | MountNode::~MountNode() {} |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 40 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 41 | Error MountNode::Init(int perm) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 42 | stat_.st_mode |= perm; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 43 | return 0; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 44 | } |
| 45 | |
| 46 | void MountNode::Destroy() { |
| 47 | if (mount_) { |
| 48 | mount_->OnNodeDestroyed(this); |
| 49 | } |
| 50 | } |
| 51 | |
Ben Murdoch | fb25065 | 2013-07-31 11:42:55 +0100 | [diff] [blame] | 52 | // Declared in EventEmitter, default to regular files which always return |
Ben Murdoch | 3240926 | 2013-08-07 11:04:47 +0100 | [diff] [blame] | 53 | // a ready of TRUE for read, write, or error. |
Ben Murdoch | fb25065 | 2013-07-31 11:42:55 +0100 | [diff] [blame] | 54 | uint32_t MountNode::GetEventStatus() { |
Ben Murdoch | 3240926 | 2013-08-07 11:04:47 +0100 | [diff] [blame] | 55 | uint32_t val = POLLIN | POLLOUT | POLLERR; |
| 56 | return val; |
Ben Murdoch | fb25065 | 2013-07-31 11:42:55 +0100 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 60 | Error MountNode::FSync() { return 0; } |
| 61 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 62 | Error MountNode::FTruncate(off_t length) { return EINVAL; } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 63 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 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; |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 70 | } |
| 71 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 72 | Error MountNode::GetStat(struct stat* pstat) { |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 73 | AUTO_LOCK(node_lock_); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 74 | memcpy(pstat, &stat_, sizeof(stat_)); |
| 75 | return 0; |
| 76 | } |
| 77 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 78 | Error MountNode::Ioctl(int request, char* arg) { return EINVAL; } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 79 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 80 | Error MountNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) { |
| 81 | *out_bytes = 0; |
| 82 | return EINVAL; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 83 | } |
| 84 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 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; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 91 | } |
| 92 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 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 | |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 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. |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 104 | if (prot & PROT_EXEC) |
| 105 | return EPERM; |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 106 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 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; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 110 | int mmap_error = _real_mmap( |
| 111 | &new_addr, length, prot | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 112 | if (new_addr == MAP_FAILED) { |
| 113 | _real_munmap(new_addr, length); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 114 | return mmap_error; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 115 | } |
| 116 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 117 | int bytes_read; |
| 118 | Error read_error = Read(offset, new_addr, length, &bytes_read); |
| 119 | if (read_error) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 120 | _real_munmap(new_addr, length); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 121 | return read_error; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 122 | } |
| 123 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 124 | *out_addr = new_addr; |
| 125 | return 0; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 126 | } |
| 127 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 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 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 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; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 148 | } |
| 149 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 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 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 158 | Error MountNode::AddChild(const std::string& name, |
| 159 | const ScopedMountNode& node) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 160 | return ENOTDIR; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 161 | } |
| 162 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 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); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 167 | return ENOTDIR; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 168 | } |
| 169 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 170 | int MountNode::ChildCount() { return 0; } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 171 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 172 | void MountNode::Link() { stat_.st_nlink++; } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 173 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 174 | void MountNode::Unlink() { stat_.st_nlink--; } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 175 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 176 | } // namespace nacl_io |
| 177 | |