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