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 (!node_
->CanOpen(open_flags
)) {
47 if (open_flags
& O_APPEND
) {
48 Error error
= node_
->GetSize(&handle_attr_
.offs
);
56 Error
KernelHandle::Seek(off_t offset
, int whence
, off_t
* out_offset
) {
57 // By default, don't move the offset.
62 AUTO_LOCK(handle_lock_
);
63 Error error
= node_
->GetSize(&node_size
);
72 base
= handle_attr_
.offs
;
81 if (base
+ offset
< 0)
84 off_t new_offset
= base
+ offset
;
86 // Seeking past the end of the file will zero out the space between the old
87 // end and the new end.
88 if (new_offset
> node_size
) {
89 error
= node_
->FTruncate(new_offset
);
94 *out_offset
= handle_attr_
.offs
= new_offset
;
98 Error
KernelHandle::Read(void* buf
, size_t nbytes
, int* cnt
) {
99 AUTO_LOCK(handle_lock_
);
100 if (OpenMode() == O_WRONLY
)
102 Error error
= node_
->Read(handle_attr_
, buf
, nbytes
, cnt
);
104 handle_attr_
.offs
+= *cnt
;
108 Error
KernelHandle::Write(const void* buf
, size_t nbytes
, int* cnt
) {
109 AUTO_LOCK(handle_lock_
);
110 if (OpenMode() == O_RDONLY
)
112 Error error
= node_
->Write(handle_attr_
, buf
, nbytes
, cnt
);
114 handle_attr_
.offs
+= *cnt
;
118 Error
KernelHandle::GetDents(struct dirent
* pdir
, size_t nbytes
, int* cnt
) {
119 AUTO_LOCK(handle_lock_
);
120 Error error
= node_
->GetDents(handle_attr_
.offs
, pdir
, nbytes
, cnt
);
122 handle_attr_
.offs
+= *cnt
;
126 Error
KernelHandle::Fcntl(int request
, int* result
, ...) {
128 va_start(ap
, result
);
129 Error rtn
= VFcntl(request
, result
, ap
);
134 Error
KernelHandle::VFcntl(int request
, int* result
, va_list args
) {
137 *result
= handle_attr_
.flags
;
141 AUTO_LOCK(handle_lock_
);
142 int flags
= va_arg(args
, int);
143 if (!(flags
& O_APPEND
) && (handle_attr_
.flags
& O_APPEND
)) {
144 // Attempt to clear O_APPEND.
147 // Only certain flags are mutable
148 const int mutable_flags
= O_ASYNC
| O_NONBLOCK
;
149 flags
&= mutable_flags
;
150 handle_attr_
.flags
&= ~mutable_flags
;
151 handle_attr_
.flags
|= flags
;
155 LOG_ERROR("Unsupported fcntl: %#x", request
);
161 Error
KernelHandle::Accept(PP_Resource
* new_sock
,
162 struct sockaddr
* addr
,
164 SocketNode
* sock
= socket_node();
168 AUTO_LOCK(handle_lock_
);
169 return sock
->Accept(handle_attr_
, new_sock
, addr
, len
);
172 Error
KernelHandle::Connect(const struct sockaddr
* addr
, socklen_t len
) {
173 SocketNode
* sock
= socket_node();
177 AUTO_LOCK(handle_lock_
);
178 return sock
->Connect(handle_attr_
, addr
, len
);
181 Error
KernelHandle::Recv(void* buf
, size_t len
, int flags
, int* out_len
) {
182 SocketNode
* sock
= socket_node();
185 if (OpenMode() == O_WRONLY
)
188 AUTO_LOCK(handle_lock_
);
189 return sock
->Recv(handle_attr_
, buf
, len
, flags
, out_len
);
192 Error
KernelHandle::RecvFrom(void* buf
,
195 struct sockaddr
* src_addr
,
198 SocketNode
* sock
= socket_node();
201 if (OpenMode() == O_WRONLY
)
204 AUTO_LOCK(handle_lock_
);
205 return sock
->RecvFrom(handle_attr_
, buf
, len
, flags
, src_addr
, addrlen
,
209 Error
KernelHandle::Send(const void* buf
, size_t len
, int flags
, int* out_len
) {
210 SocketNode
* sock
= socket_node();
213 if (OpenMode() == O_RDONLY
)
216 AUTO_LOCK(handle_lock_
);
217 return sock
->Send(handle_attr_
, buf
, len
, flags
, out_len
);
220 Error
KernelHandle::SendTo(const void* buf
,
223 const struct sockaddr
* dest_addr
,
226 SocketNode
* sock
= socket_node();
229 if (OpenMode() == O_RDONLY
)
232 AUTO_LOCK(handle_lock_
);
233 return sock
->SendTo(handle_attr_
, buf
, len
, flags
, dest_addr
, addrlen
,
237 } // namespace nacl_io