| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "nacl_io/kernel_handle.h" | 5 #include "nacl_io/kernel_handle.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <pthread.h> | 8 #include <pthread.h> |
| 9 | 9 |
| 10 #include "nacl_io/mount.h" | 10 #include "nacl_io/mount.h" |
| 11 #include "nacl_io/mount_node.h" | 11 #include "nacl_io/mount_node.h" |
| 12 #include "nacl_io/mount_node_socket.h" |
| 12 #include "nacl_io/osunistd.h" | 13 #include "nacl_io/osunistd.h" |
| 13 | 14 |
| 14 #include "sdk_util/auto_lock.h" | 15 #include "sdk_util/auto_lock.h" |
| 15 | 16 |
| 16 namespace nacl_io { | 17 namespace nacl_io { |
| 17 | 18 |
| 18 // It is only legal to construct a handle while the kernel lock is held. | 19 // It is only legal to construct a handle while the kernel lock is held. |
| 19 KernelHandle::KernelHandle() | 20 KernelHandle::KernelHandle() |
| 20 : mount_(NULL), node_(NULL) {} | 21 : mount_(NULL), node_(NULL) {} |
| 21 | 22 |
| 22 KernelHandle::KernelHandle(const ScopedMount& mnt, const ScopedMountNode& node) | 23 KernelHandle::KernelHandle(const ScopedMount& mnt, const ScopedMountNode& node) |
| 23 : mount_(mnt), node_(node) {} | 24 : mount_(mnt), node_(node) {} |
| 24 | 25 |
| 25 KernelHandle::~KernelHandle() { | 26 KernelHandle::~KernelHandle() { |
| 26 // Force release order for cases where mount_ is not ref'd by mounting. | 27 // Force release order for cases where mount_ is not ref'd by mounting. |
| 27 node_.reset(NULL); | 28 node_.reset(NULL); |
| 28 mount_.reset(NULL); | 29 mount_.reset(NULL); |
| 29 } | 30 } |
| 30 | 31 |
| 31 // Returns the MountNodeSocket* if this node is a socket. | 32 // Returns the MountNodeSocket* if this node is a socket. |
| 32 MountNodeSocket* KernelHandle::socket_node() { | 33 MountNodeSocket* KernelHandle::socket_node() { |
| 33 if (node_.get() && node_->IsaSock()) | 34 if (node_.get() && node_->IsaSock()) |
| 34 return reinterpret_cast<MountNodeSocket*>(node_.get()); | 35 return reinterpret_cast<MountNodeSocket*>(node_.get()); |
| 35 return NULL; | 36 return NULL; |
| 36 } | 37 } |
| 37 | 38 |
| 38 Error KernelHandle::Init(int open_flags) { | 39 Error KernelHandle::Init(int open_flags) { |
| 39 handle_data_.flags = open_flags; | 40 handle_attr_.flags = open_flags; |
| 40 | 41 |
| 41 if (open_flags & O_APPEND) { | 42 if (open_flags & O_APPEND) { |
| 42 Error error = node_->GetSize(&handle_data_.offs); | 43 Error error = node_->GetSize(&handle_attr_.offs); |
| 43 if (error) | 44 if (error) |
| 44 return error; | 45 return error; |
| 45 } | 46 } |
| 46 | 47 |
| 47 return 0; | 48 return 0; |
| 48 } | 49 } |
| 49 | 50 |
| 50 Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) { | 51 Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) { |
| 51 // By default, don't move the offset. | 52 // By default, don't move the offset. |
| 52 *out_offset = offset; | 53 *out_offset = offset; |
| 53 size_t base; | 54 size_t base; |
| 54 size_t node_size; | 55 size_t node_size; |
| 55 | 56 |
| 56 AUTO_LOCK(handle_lock_); | 57 AUTO_LOCK(handle_lock_); |
| 57 Error error = node_->GetSize(&node_size); | 58 Error error = node_->GetSize(&node_size); |
| 58 if (error) | 59 if (error) |
| 59 return error; | 60 return error; |
| 60 | 61 |
| 61 switch (whence) { | 62 switch (whence) { |
| 62 default: | 63 default: |
| 63 return -1; | 64 return -1; |
| 64 case SEEK_SET: | 65 case SEEK_SET: |
| 65 base = 0; | 66 base = 0; |
| 66 break; | 67 break; |
| 67 case SEEK_CUR: | 68 case SEEK_CUR: |
| 68 base = handle_data_.offs; | 69 base = handle_attr_.offs; |
| 69 break; | 70 break; |
| 70 case SEEK_END: | 71 case SEEK_END: |
| 71 base = node_size; | 72 base = node_size; |
| 72 break; | 73 break; |
| 73 } | 74 } |
| 74 | 75 |
| 75 if (base + offset < 0) | 76 if (base + offset < 0) |
| 76 return EINVAL; | 77 return EINVAL; |
| 77 | 78 |
| 78 off_t new_offset = base + offset; | 79 off_t new_offset = base + offset; |
| 79 | 80 |
| 80 // Seeking past the end of the file will zero out the space between the old | 81 // Seeking past the end of the file will zero out the space between the old |
| 81 // end and the new end. | 82 // end and the new end. |
| 82 if (new_offset > node_size) { | 83 if (new_offset > node_size) { |
| 83 error = node_->FTruncate(new_offset); | 84 error = node_->FTruncate(new_offset); |
| 84 if (error) | 85 if (error) |
| 85 return EINVAL; | 86 return EINVAL; |
| 86 } | 87 } |
| 87 | 88 |
| 88 *out_offset = handle_data_.offs = new_offset; | 89 *out_offset = handle_attr_.offs = new_offset; |
| 89 return 0; | 90 return 0; |
| 90 } | 91 } |
| 91 | 92 |
| 92 Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) { | 93 Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) { |
| 93 AUTO_LOCK(handle_lock_); | 94 AUTO_LOCK(handle_lock_); |
| 94 Error error = node_->Read(handle_data_, buf, nbytes, cnt); | 95 Error error = node_->Read(handle_attr_, buf, nbytes, cnt); |
| 95 if (0 == error) | 96 if (0 == error) |
| 96 handle_data_.offs += *cnt; | 97 handle_attr_.offs += *cnt; |
| 97 return error; | 98 return error; |
| 98 } | 99 } |
| 99 | 100 |
| 100 Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) { | 101 Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) { |
| 101 AUTO_LOCK(handle_lock_); | 102 AUTO_LOCK(handle_lock_); |
| 102 Error error = node_->Write(handle_data_, buf, nbytes, cnt); | 103 Error error = node_->Write(handle_attr_, buf, nbytes, cnt); |
| 103 if (0 == error) | 104 if (0 == error) |
| 104 handle_data_.offs += *cnt; | 105 handle_attr_.offs += *cnt; |
| 105 return error; | 106 return error; |
| 106 } | 107 } |
| 107 | 108 |
| 108 Error KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) { | 109 Error KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) { |
| 109 AUTO_LOCK(handle_lock_); | 110 AUTO_LOCK(handle_lock_); |
| 110 Error error = node_->GetDents(handle_data_.offs, pdir, nbytes, cnt); | 111 Error error = node_->GetDents(handle_attr_.offs, pdir, nbytes, cnt); |
| 111 if (0 == error) | 112 if (0 == error) |
| 112 handle_data_.offs += *cnt; | 113 handle_attr_.offs += *cnt; |
| 113 return error; | 114 return error; |
| 114 } | 115 } |
| 115 | 116 |
| 116 Error KernelHandle::Fcntl(int request, int* result, ...) { | 117 Error KernelHandle::Fcntl(int request, int* result, ...) { |
| 117 va_list ap; | 118 va_list ap; |
| 118 va_start(ap, result); | 119 va_start(ap, result); |
| 119 Error rtn = VFcntl(request, result, ap); | 120 Error rtn = VFcntl(request, result, ap); |
| 120 va_end(ap); | 121 va_end(ap); |
| 121 return rtn; | 122 return rtn; |
| 122 } | 123 } |
| 123 | 124 |
| 124 Error KernelHandle::VFcntl(int request, int* result, va_list args) { | 125 Error KernelHandle::VFcntl(int request, int* result, va_list args) { |
| 125 switch (request) { | 126 switch (request) { |
| 126 case F_GETFL: { | 127 case F_GETFL: { |
| 127 *result = handle_data_.flags; | 128 *result = handle_attr_.flags; |
| 128 return 0; | 129 return 0; |
| 129 } | 130 } |
| 130 case F_SETFL: { | 131 case F_SETFL: { |
| 131 AUTO_LOCK(handle_lock_); | 132 AUTO_LOCK(handle_lock_); |
| 132 int flags = va_arg(args, int); | 133 int flags = va_arg(args, int); |
| 133 if (!(flags & O_APPEND) && (handle_data_.flags & O_APPEND)) { | 134 if (!(flags & O_APPEND) && (handle_attr_.flags & O_APPEND)) { |
| 134 // Attempt to clear O_APPEND. | 135 // Attempt to clear O_APPEND. |
| 135 return EPERM; | 136 return EPERM; |
| 136 } | 137 } |
| 137 // Only certain flags are mutable | 138 // Only certain flags are mutable |
| 138 const int mutable_flags = O_ASYNC | O_NONBLOCK; | 139 const int mutable_flags = O_ASYNC | O_NONBLOCK; |
| 139 flags &= mutable_flags; | 140 flags &= mutable_flags; |
| 140 handle_data_.flags &= ~mutable_flags; | 141 handle_attr_.flags &= ~mutable_flags; |
| 141 handle_data_.flags |= flags; | 142 handle_attr_.flags |= flags; |
| 142 return 0; | 143 return 0; |
| 143 } | 144 } |
| 144 } | 145 } |
| 145 return ENOSYS; | 146 return ENOSYS; |
| 146 } | 147 } |
| 147 | 148 |
| 149 Error KernelHandle::Accept(PP_Resource* new_sock, struct sockaddr* addr, |
| 150 socklen_t* len) { |
| 151 MountNodeSocket* sock = socket_node(); |
| 152 if (!sock) |
| 153 return ENOTSOCK; |
| 154 |
| 155 AUTO_LOCK(handle_lock_); |
| 156 return sock->Accept(handle_attr_, new_sock, addr, len); |
| 157 } |
| 158 |
| 159 Error KernelHandle::Connect(const struct sockaddr* addr, socklen_t len) { |
| 160 MountNodeSocket* sock = socket_node(); |
| 161 if (!sock) |
| 162 return ENOTSOCK; |
| 163 |
| 164 AUTO_LOCK(handle_lock_); |
| 165 return sock->Connect(handle_attr_, addr, len); |
| 166 } |
| 167 |
| 168 Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) { |
| 169 MountNodeSocket* sock = socket_node(); |
| 170 if (!sock) |
| 171 return ENOTSOCK; |
| 172 |
| 173 AUTO_LOCK(handle_lock_); |
| 174 return sock->Recv(handle_attr_, buf, len, flags, out_len); |
| 175 } |
| 176 |
| 177 Error KernelHandle::RecvFrom(void* buf, |
| 178 size_t len, |
| 179 int flags, |
| 180 struct sockaddr* src_addr, |
| 181 socklen_t* addrlen, |
| 182 int* out_len) { |
| 183 MountNodeSocket* sock = socket_node(); |
| 184 if (!sock) |
| 185 return ENOTSOCK; |
| 186 |
| 187 AUTO_LOCK(handle_lock_); |
| 188 return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen, |
| 189 out_len); |
| 190 } |
| 191 |
| 192 Error KernelHandle::Send(const void* buf, |
| 193 size_t len, |
| 194 int flags, |
| 195 int* out_len) { |
| 196 MountNodeSocket* sock = socket_node(); |
| 197 if (!sock) |
| 198 return ENOTSOCK; |
| 199 |
| 200 AUTO_LOCK(handle_lock_); |
| 201 return sock->Send(handle_attr_, buf, len, flags, out_len); |
| 202 } |
| 203 |
| 204 Error KernelHandle::SendTo(const void* buf, |
| 205 size_t len, |
| 206 int flags, |
| 207 const struct sockaddr* dest_addr, |
| 208 socklen_t addrlen, |
| 209 int* out_len) { |
| 210 MountNodeSocket* sock = socket_node(); |
| 211 if (!sock) |
| 212 return ENOTSOCK; |
| 213 |
| 214 AUTO_LOCK(handle_lock_); |
| 215 return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen, |
| 216 out_len); |
| 217 } |
| 218 |
| 148 } // namespace nacl_io | 219 } // namespace nacl_io |
| OLD | NEW |