2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * NaCl Service Runtime. I/O Descriptor / Handle abstraction. Memory
34 * mapping using descriptors.
37 #include "native_client/include/portability.h"
46 #include "native_client/service_runtime/nacl_desc_io.h"
48 #include "native_client/service_runtime/internal_errno.h"
50 #include "native_client/service_runtime/nacl_config.h"
51 #include "native_client/service_runtime/nacl_log.h"
52 #include "native_client/service_runtime/nacl_desc_base.h"
53 #include "native_client/service_runtime/nacl_desc_effector.h"
55 #include "native_client/service_runtime/include/sys/errno.h"
56 #include "native_client/service_runtime/include/sys/fcntl.h"
57 #include "native_client/service_runtime/include/sys/mman.h"
59 #include "native_client/intermodule_comm/nacl_imc_c.h"
62 * This file contains the implementation for the NaClIoDesc subclass
65 * NaClDescIoDesc is the subclass that wraps host-OS descriptors
66 * provided by NaClHostDesc (which gives an OS-independent abstraction
67 * for host-OS descriptors).
71 * Takes ownership of hd, will close in Dtor.
73 int NaClDescIoDescCtor(struct NaClDescIoDesc
*self
,
74 struct NaClHostDesc
*hd
)
76 struct NaClDesc
*basep
= (struct NaClDesc
*) self
;
78 if (!NaClDescCtor(basep
)) {
82 basep
->vtbl
= &kNaClDescIoDescVtbl
;
86 void NaClDescIoDescDtor(struct NaClDesc
*vself
)
88 struct NaClDescIoDesc
*self
= (struct NaClDescIoDesc
*) vself
;
90 NaClLog(4, "NaClDescIoDescDtor(0x%08x).\n",
92 NaClHostDescClose(self
->hd
);
95 NaClDescDtor(&self
->base
);
98 struct NaClDescIoDesc
*NaClDescIoDescMake(struct NaClHostDesc
*nhdp
)
100 struct NaClDescIoDesc
*ndp
;
102 ndp
= malloc(sizeof *ndp
);
105 "NaClDescIoDescMake: no memory for 0x%08x\n",
108 if (!NaClDescIoDescCtor(ndp
, nhdp
)) {
110 "NaClDescIoDescMake: NaClDescIoDescCtor(0x%08x,0x%08x) failed\n",
117 struct NaClDescIoDesc
*NaClDescIoDescOpen(char *path
,
121 struct NaClHostDesc
*nhdp
;
123 nhdp
= malloc(sizeof *nhdp
);
125 NaClLog(LOG_FATAL
, "NaClDescIoDescOpen: no memory for %s\n", path
);
127 if (!NaClHostDescOpen(nhdp
, path
, mode
, perms
)) {
128 NaClLog(LOG_FATAL
, "NaClDescIoDescOpen: NaClHostDescOpen failed for %s\n",
131 return NaClDescIoDescMake(nhdp
);
134 int NaClDescIoDescMap(struct NaClDesc
*vself
,
135 struct NaClDescEffector
*effp
,
142 struct NaClDescIoDesc
*self
= (struct NaClDescIoDesc
*) vself
;
147 * prot must be PROT_NONE or a combination of PROT_{READ|WRITE}
149 if (0 != (~(NACL_ABI_PROT_READ
| NACL_ABI_PROT_WRITE
) & prot
)) {
151 ("NaClDescImcDescMap: prot has other bits"
152 " than PROT_{READ|WRITE}\n"));
153 return -NACL_ABI_EINVAL
;
156 if (0 != (rv
= (*effp
->vtbl
->UnmapMemory
)(effp
,
157 (uintptr_t) start_addr
,
160 ("NaClDescIoDescMap: error %d --"
161 " could not unmap 0x%08x, length 0x%x\n"),
163 (uintptr_t) start_addr
,
167 status
= NaClHostDescMap((NULL
== self
) ? NULL
: self
->hd
,
176 int NaClDescIoDescUnmapCommon(struct NaClDesc
*vself
,
177 struct NaClDescEffector
*effp
,
185 status
= NaClHostDescUnmap(start_addr
, len
);
187 status
= NaClHostDescUnmapUnsafe(start_addr
, len
);
194 * NB: User code should never be able to invoke the Unsafe method.
196 int NaClDescIoDescUnmapUnsafe(struct NaClDesc
*vself
,
197 struct NaClDescEffector
*effp
,
201 return NaClDescIoDescUnmapCommon(vself
, effp
, start_addr
, len
, 0);
204 int NaClDescIoDescUnmap(struct NaClDesc
*vself
,
205 struct NaClDescEffector
*effp
,
209 return NaClDescIoDescUnmapCommon(vself
, effp
, start_addr
, len
, 1);
212 ssize_t
NaClDescIoDescRead(struct NaClDesc
*vself
,
213 struct NaClDescEffector
*effp
,
217 struct NaClDescIoDesc
*self
= (struct NaClDescIoDesc
*) vself
;
219 return NaClHostDescRead(self
->hd
, buf
, len
);
222 ssize_t
NaClDescIoDescWrite(struct NaClDesc
*vself
,
223 struct NaClDescEffector
*effp
,
227 struct NaClDescIoDesc
*self
= (struct NaClDescIoDesc
*) vself
;
229 return NaClHostDescWrite(self
->hd
, buf
, len
);
232 int NaClDescIoDescSeek(struct NaClDesc
*vself
,
233 struct NaClDescEffector
*effp
,
237 struct NaClDescIoDesc
*self
= (struct NaClDescIoDesc
*) vself
;
239 return NaClHostDescSeek(self
->hd
, offset
, whence
);
242 int NaClDescIoDescIoctl(struct NaClDesc
*vself
,
243 struct NaClDescEffector
*effp
,
247 struct NaClDescIoDesc
*self
= (struct NaClDescIoDesc
*) vself
;
249 return NaClHostDescIoctl(self
->hd
, request
, arg
);
252 int NaClDescIoDescFstat(struct NaClDesc
*vself
,
253 struct NaClDescEffector
*effp
,
254 struct nacl_abi_stat
*statbuf
)
256 struct NaClDescIoDesc
*self
= (struct NaClDescIoDesc
*) vself
;
258 return NaClHostDescFstat(self
->hd
, statbuf
);
261 int NaClDescIoDescClose(struct NaClDesc
*vself
,
262 struct NaClDescEffector
*effp
)
264 NaClDescUnref(vself
);
268 int NaClDescIoDescExternalizeSize(struct NaClDesc
*vself
,
278 * TODO -- this depends on implementation of IMC being able to xfer
279 * Unix descriptors or Windows Handles as NaclHandles. Should this be
280 * part of IMC requirements? Also, Windows POSIX layer library may have
281 * strange side effects due to extra buffering. TEST AND DECIDE.
283 int NaClDescIoDescExternalize(struct NaClDesc
*vself
,
284 struct NaClDescXferState
*xfer
)
286 struct NaClDescIoDesc
*self
= (struct NaClDescIoDesc
*) vself
;
289 HANDLE h
= (HANDLE
) _get_osfhandle(self
->hd
->d
);
291 NaClLog(LOG_WARNING
, "NaClDescIoDescExternalize is EXPERIMENTAL\n");
292 NaClLog(LOG_WARNING
, "handle 0x%x\n", (uintptr_t) h
);
294 *xfer
->next_handle
++ = (NaClHandle
) h
;
296 *xfer
->next_handle
++ = self
->hd
->d
;
301 struct NaClDescVtbl
const kNaClDescIoDescVtbl
= {
304 NaClDescIoDescUnmapUnsafe
,
312 NaClDescGetdentsNotImplemented
,
314 NaClDescIoDescExternalizeSize
,
315 NaClDescIoDescExternalize
,
316 NaClDescLockNotImplemented
,
317 NaClDescTryLockNotImplemented
,
318 NaClDescUnlockNotImplemented
,
319 NaClDescWaitNotImplemented
,
320 NaClDescTimedWaitAbsNotImplemented
,
321 NaClDescSignalNotImplemented
,
322 NaClDescBroadcastNotImplemented
,
323 NaClDescSendMsgNotImplemented
,
324 NaClDescRecvMsgNotImplemented
,
325 NaClDescConnectAddrNotImplemented
,
326 NaClDescAcceptConnNotImplemented
,
327 NaClDescPostNotImplemented
,
328 NaClDescSemWaitNotImplemented
,
329 NaClDescGetValueNotImplemented
,
332 /* set *baseptr to struct NaClDescIo * output */
333 int NaClDescIoInternalize(struct NaClDesc
**baseptr
,
334 struct NaClDescXferState
*xfer
)
339 struct NaClHostDesc
*nhdp
;
340 struct NaClDescIoDesc
*ndidp
;
342 rv
= -NACL_ABI_EIO
; /* catch-all */
343 h
= NACL_INVALID_HANDLE
;
347 if (xfer
->next_handle
== xfer
->handle_buffer_end
) {
351 nhdp
= malloc(sizeof *nhdp
);
353 rv
= -NACL_ABI_ENOMEM
;
356 ndidp
= malloc(sizeof *ndidp
);
358 rv
= -NACL_ABI_ENOMEM
;
361 h
= *xfer
->next_handle
;
362 *xfer
->next_handle
++ = NACL_INVALID_HANDLE
;
364 if (-1 == (d
= _open_osfhandle((intptr_t) h
, _O_RDWR
| _O_BINARY
))) {
372 * We mark it as read/write, but don't really know for sure until we
373 * try to make those syscalls (in which case we'd get EBADF).
375 if ((rv
= NaClHostDescPosixTake(nhdp
, d
, NACL_ABI_O_RDWR
)) < 0) {
378 h
= NACL_INVALID_HANDLE
; /* nhdp took ownership of h */
380 if (!NaClDescIoDescCtor(ndidp
, nhdp
)) {
381 rv
= -NACL_ABI_ENOMEM
;
382 goto cleanup_hd_dtor
;
385 * ndidp took ownership of nhdp, now give ownership of ndidp to caller.
387 *baseptr
= (struct NaClDesc
*) ndidp
;
391 (void) NaClHostDescClose(nhdp
);
397 if (NACL_INVALID_HANDLE
!= h
) {