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.
5 #include "nacl_io/kernel_handle.h"
10 #include "nacl_io/filesystem.h"
11 #include "nacl_io/node.h"
12 #include "nacl_io/osunistd.h"
13 #include "nacl_io/socket/socket_node.h"
15 #include "sdk_util/auto_lock.h"
19 // It is only legal to construct a handle while the kernel lock is held.
20 KernelHandle::KernelHandle() : filesystem_(NULL), node_(NULL) {
23 KernelHandle::KernelHandle(const ScopedFilesystem& fs, const ScopedNode& node)
24 : filesystem_(fs), node_(node) {
27 KernelHandle::~KernelHandle() {
28 // Force release order for cases where filesystem_ is not ref'd by mounting.
30 filesystem_.reset(NULL);
33 // Returns the SocketNode* if this node is a socket.
34 SocketNode* KernelHandle::socket_node() {
35 if (node_.get() && node_->IsaSock())
36 return reinterpret_cast<SocketNode*>(node_.get());
40 Error KernelHandle::Init(int open_flags) {
41 handle_attr_.flags = open_flags;
43 if ((open_flags & O_CREAT) == 0 && !node_->CanOpen(open_flags)) {
47 // Directories can only be opened read-only.
48 if ((open_flags & 3) != O_RDONLY && node_->IsaDir()) {
52 if (open_flags & O_APPEND) {
53 Error error = node_->GetSize(&handle_attr_.offs);
61 Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) {
62 // By default, don't move the offset.
67 AUTO_LOCK(handle_lock_);
68 Error error = node_->GetSize(&node_size);
77 base = handle_attr_.offs;
86 if (base + offset < 0)
89 off_t new_offset = base + offset;
91 // Seeking past the end of the file will zero out the space between the old
92 // end and the new end.
93 if (new_offset > node_size) {
94 error = node_->FTruncate(new_offset);
99 *out_offset = handle_attr_.offs = new_offset;
103 Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) {
104 AUTO_LOCK(handle_lock_);
105 if (OpenMode() == O_WRONLY)
107 Error error = node_->Read(handle_attr_, buf, nbytes, cnt);
109 handle_attr_.offs += *cnt;
113 Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) {
114 AUTO_LOCK(handle_lock_);
115 if (OpenMode() == O_RDONLY)
117 Error error = node_->Write(handle_attr_, buf, nbytes, cnt);
119 handle_attr_.offs += *cnt;
123 Error KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) {
124 AUTO_LOCK(handle_lock_);
125 Error error = node_->GetDents(handle_attr_.offs, pdir, nbytes, cnt);
127 handle_attr_.offs += *cnt;
131 Error KernelHandle::Fcntl(int request, int* result, ...) {
133 va_start(ap, result);
134 Error rtn = VFcntl(request, result, ap);
139 Error KernelHandle::VFcntl(int request, int* result, va_list args) {
142 *result = handle_attr_.flags;
146 AUTO_LOCK(handle_lock_);
147 int flags = va_arg(args, int);
148 if (!(flags & O_APPEND) && (handle_attr_.flags & O_APPEND)) {
149 // Attempt to clear O_APPEND.
152 // Only certain flags are mutable
153 const int mutable_flags = O_ASYNC | O_NONBLOCK;
154 flags &= mutable_flags;
155 handle_attr_.flags &= ~mutable_flags;
156 handle_attr_.flags |= flags;
160 LOG_ERROR("Unsupported fcntl: %#x", request);
166 Error KernelHandle::Accept(PP_Resource* new_sock,
167 struct sockaddr* addr,
169 SocketNode* sock = socket_node();
173 AUTO_LOCK(handle_lock_);
174 return sock->Accept(handle_attr_, new_sock, addr, len);
177 Error KernelHandle::Connect(const struct sockaddr* addr, socklen_t len) {
178 SocketNode* sock = socket_node();
182 AUTO_LOCK(handle_lock_);
183 return sock->Connect(handle_attr_, addr, len);
186 Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) {
187 SocketNode* sock = socket_node();
190 if (OpenMode() == O_WRONLY)
193 AUTO_LOCK(handle_lock_);
194 return sock->Recv(handle_attr_, buf, len, flags, out_len);
197 Error KernelHandle::RecvFrom(void* buf,
200 struct sockaddr* src_addr,
203 SocketNode* sock = socket_node();
206 if (OpenMode() == O_WRONLY)
209 AUTO_LOCK(handle_lock_);
210 return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen,
214 Error KernelHandle::Send(const void* buf, size_t len, int flags, int* out_len) {
215 SocketNode* sock = socket_node();
218 if (OpenMode() == O_RDONLY)
221 AUTO_LOCK(handle_lock_);
222 return sock->Send(handle_attr_, buf, len, flags, out_len);
225 Error KernelHandle::SendTo(const void* buf,
228 const struct sockaddr* dest_addr,
231 SocketNode* sock = socket_node();
234 if (OpenMode() == O_RDONLY)
237 AUTO_LOCK(handle_lock_);
238 return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen,
242 } // namespace nacl_io