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/mount.h"
11 #include "nacl_io/mount_node.h"
12 #include "nacl_io/mount_node_socket.h"
13 #include "nacl_io/osunistd.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()
21 : mount_(NULL), node_(NULL) {}
23 KernelHandle::KernelHandle(const ScopedMount& mnt, const ScopedMountNode& node)
24 : mount_(mnt), node_(node) {}
26 KernelHandle::~KernelHandle() {
27 // Force release order for cases where mount_ is not ref'd by mounting.
32 // Returns the MountNodeSocket* if this node is a socket.
33 MountNodeSocket* KernelHandle::socket_node() {
34 if (node_.get() && node_->IsaSock())
35 return reinterpret_cast<MountNodeSocket*>(node_.get());
39 Error KernelHandle::Init(int open_flags) {
40 handle_attr_.flags = open_flags;
42 if (!node_->CanOpen(open_flags)) {
46 if (open_flags & O_APPEND) {
47 Error error = node_->GetSize(&handle_attr_.offs);
55 Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) {
56 // By default, don't move the offset.
61 AUTO_LOCK(handle_lock_);
62 Error error = node_->GetSize(&node_size);
73 base = handle_attr_.offs;
80 if (base + offset < 0)
83 off_t new_offset = base + offset;
85 // Seeking past the end of the file will zero out the space between the old
86 // end and the new end.
87 if (new_offset > node_size) {
88 error = node_->FTruncate(new_offset);
93 *out_offset = handle_attr_.offs = new_offset;
97 Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) {
98 AUTO_LOCK(handle_lock_);
99 if (OpenMode() == O_WRONLY)
101 Error error = node_->Read(handle_attr_, buf, nbytes, cnt);
103 handle_attr_.offs += *cnt;
107 Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) {
108 AUTO_LOCK(handle_lock_);
109 if (OpenMode() == O_RDONLY)
111 Error error = node_->Write(handle_attr_, buf, nbytes, cnt);
113 handle_attr_.offs += *cnt;
117 Error KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) {
118 AUTO_LOCK(handle_lock_);
119 Error error = node_->GetDents(handle_attr_.offs, pdir, nbytes, cnt);
121 handle_attr_.offs += *cnt;
125 Error KernelHandle::Fcntl(int request, int* result, ...) {
127 va_start(ap, result);
128 Error rtn = VFcntl(request, result, ap);
133 Error KernelHandle::VFcntl(int request, int* result, va_list args) {
136 *result = handle_attr_.flags;
140 AUTO_LOCK(handle_lock_);
141 int flags = va_arg(args, int);
142 if (!(flags & O_APPEND) && (handle_attr_.flags & O_APPEND)) {
143 // Attempt to clear O_APPEND.
146 // Only certain flags are mutable
147 const int mutable_flags = O_ASYNC | O_NONBLOCK;
148 flags &= mutable_flags;
149 handle_attr_.flags &= ~mutable_flags;
150 handle_attr_.flags |= flags;
157 Error KernelHandle::Accept(PP_Resource* new_sock, struct sockaddr* addr,
159 MountNodeSocket* sock = socket_node();
163 AUTO_LOCK(handle_lock_);
164 return sock->Accept(handle_attr_, new_sock, addr, len);
167 Error KernelHandle::Connect(const struct sockaddr* addr, socklen_t len) {
168 MountNodeSocket* sock = socket_node();
172 AUTO_LOCK(handle_lock_);
173 return sock->Connect(handle_attr_, addr, len);
176 Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) {
177 MountNodeSocket* sock = socket_node();
181 AUTO_LOCK(handle_lock_);
182 return sock->Recv(handle_attr_, buf, len, flags, out_len);
185 Error KernelHandle::RecvFrom(void* buf,
188 struct sockaddr* src_addr,
191 MountNodeSocket* sock = socket_node();
195 AUTO_LOCK(handle_lock_);
196 return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen,
200 Error KernelHandle::Send(const void* buf,
204 MountNodeSocket* sock = socket_node();
208 AUTO_LOCK(handle_lock_);
209 return sock->Send(handle_attr_, buf, len, flags, out_len);
212 Error KernelHandle::SendTo(const void* buf,
215 const struct sockaddr* dest_addr,
218 MountNodeSocket* sock = socket_node();
222 AUTO_LOCK(handle_lock_);
223 return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen,
227 } // namespace nacl_io