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) {}
22 KernelHandle::KernelHandle(const ScopedFilesystem& fs, const ScopedNode& node)
23 : filesystem_(fs), node_(node) {}
25 KernelHandle::~KernelHandle() {
26 // Force release order for cases where filesystem_ is not ref'd by mounting.
28 filesystem_.reset(NULL);
31 // Returns the SocketNode* if this node is a socket.
32 SocketNode* KernelHandle::socket_node() {
33 if (node_.get() && node_->IsaSock())
34 return reinterpret_cast<SocketNode*>(node_.get());
38 Error KernelHandle::Init(int open_flags) {
39 handle_attr_.flags = open_flags;
41 if (!node_->CanOpen(open_flags)) {
45 if (open_flags & O_APPEND) {
46 Error error = node_->GetSize(&handle_attr_.offs);
54 Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) {
55 // By default, don't move the offset.
60 AUTO_LOCK(handle_lock_);
61 Error error = node_->GetSize(&node_size);
70 base = handle_attr_.offs;
79 if (base + offset < 0)
82 off_t new_offset = base + offset;
84 // Seeking past the end of the file will zero out the space between the old
85 // end and the new end.
86 if (new_offset > node_size) {
87 error = node_->FTruncate(new_offset);
92 *out_offset = handle_attr_.offs = new_offset;
96 Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) {
97 AUTO_LOCK(handle_lock_);
98 if (OpenMode() == O_WRONLY)
100 Error error = node_->Read(handle_attr_, buf, nbytes, cnt);
102 handle_attr_.offs += *cnt;
106 Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) {
107 AUTO_LOCK(handle_lock_);
108 if (OpenMode() == O_RDONLY)
110 Error error = node_->Write(handle_attr_, buf, nbytes, cnt);
112 handle_attr_.offs += *cnt;
116 Error KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) {
117 AUTO_LOCK(handle_lock_);
118 Error error = node_->GetDents(handle_attr_.offs, pdir, nbytes, cnt);
120 handle_attr_.offs += *cnt;
124 Error KernelHandle::Fcntl(int request, int* result, ...) {
126 va_start(ap, result);
127 Error rtn = VFcntl(request, result, ap);
132 Error KernelHandle::VFcntl(int request, int* result, va_list args) {
135 *result = handle_attr_.flags;
139 AUTO_LOCK(handle_lock_);
140 int flags = va_arg(args, int);
141 if (!(flags & O_APPEND) && (handle_attr_.flags & O_APPEND)) {
142 // Attempt to clear O_APPEND.
145 // Only certain flags are mutable
146 const int mutable_flags = O_ASYNC | O_NONBLOCK;
147 flags &= mutable_flags;
148 handle_attr_.flags &= ~mutable_flags;
149 handle_attr_.flags |= flags;
156 Error KernelHandle::Accept(PP_Resource* new_sock, struct sockaddr* addr,
158 SocketNode* sock = socket_node();
162 AUTO_LOCK(handle_lock_);
163 return sock->Accept(handle_attr_, new_sock, addr, len);
166 Error KernelHandle::Connect(const struct sockaddr* addr, socklen_t len) {
167 SocketNode* sock = socket_node();
171 AUTO_LOCK(handle_lock_);
172 return sock->Connect(handle_attr_, addr, len);
175 Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) {
176 SocketNode* sock = socket_node();
179 if (OpenMode() == O_WRONLY)
182 AUTO_LOCK(handle_lock_);
183 return sock->Recv(handle_attr_, buf, len, flags, out_len);
186 Error KernelHandle::RecvFrom(void* buf,
189 struct sockaddr* src_addr,
192 SocketNode* sock = socket_node();
195 if (OpenMode() == O_WRONLY)
198 AUTO_LOCK(handle_lock_);
199 return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen,
203 Error KernelHandle::Send(const void* buf,
207 SocketNode* sock = socket_node();
210 if (OpenMode() == O_RDONLY)
213 AUTO_LOCK(handle_lock_);
214 return sock->Send(handle_attr_, buf, len, flags, out_len);
217 Error KernelHandle::SendTo(const void* buf,
220 const struct sockaddr* dest_addr,
223 SocketNode* sock = socket_node();
226 if (OpenMode() == O_RDONLY)
229 AUTO_LOCK(handle_lock_);
230 return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen,
234 } // namespace nacl_io