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 <sys/types.h> // Include something that will define __BIONIC__.
7 // The entire file is wrapped in this #if. We do this so this .cc file can be
8 // compiled, even on a non-bionic build.
10 #if defined(__native_client__) && defined(__BIONIC__)
15 #include <irt_syscalls.h>
20 #include "nacl_io/kernel_intercept.h"
21 #include "nacl_io/kernel_wrap.h"
22 #include "nacl_io/kernel_wrap_real.h"
23 #include "nacl_io/osmman.h"
27 void stat_to_nacl_stat(const struct stat
* buf
, nacl_abi_stat
* nacl_buf
) {
28 memset(nacl_buf
, 0, sizeof(struct nacl_abi_stat
));
29 nacl_buf
->nacl_abi_st_dev
= buf
->st_dev
;
30 nacl_buf
->nacl_abi_st_ino
= buf
->st_ino
;
31 nacl_buf
->nacl_abi_st_mode
= buf
->st_mode
;
32 nacl_buf
->nacl_abi_st_nlink
= buf
->st_nlink
;
33 nacl_buf
->nacl_abi_st_uid
= buf
->st_uid
;
34 nacl_buf
->nacl_abi_st_gid
= buf
->st_gid
;
35 nacl_buf
->nacl_abi_st_rdev
= buf
->st_rdev
;
36 nacl_buf
->nacl_abi_st_size
= buf
->st_size
;
37 nacl_buf
->nacl_abi_st_blksize
= buf
->st_blksize
;
38 nacl_buf
->nacl_abi_st_blocks
= buf
->st_blocks
;
39 nacl_buf
->nacl_abi_st_atime
= buf
->st_atime
;
40 nacl_buf
->nacl_abi_st_mtime
= buf
->st_mtime
;
41 nacl_buf
->nacl_abi_st_ctime
= buf
->st_ctime
;
44 void nacl_stat_to_stat(const nacl_abi_stat
* nacl_buf
, struct stat
* buf
) {
45 memset(buf
, 0, sizeof(struct stat
));
46 buf
->st_dev
= nacl_buf
->nacl_abi_st_dev
;
47 buf
->st_ino
= nacl_buf
->nacl_abi_st_ino
;
48 buf
->st_mode
= nacl_buf
->nacl_abi_st_mode
;
49 buf
->st_nlink
= nacl_buf
->nacl_abi_st_nlink
;
50 buf
->st_uid
= nacl_buf
->nacl_abi_st_uid
;
51 buf
->st_gid
= nacl_buf
->nacl_abi_st_gid
;
52 buf
->st_rdev
= nacl_buf
->nacl_abi_st_rdev
;
53 buf
->st_size
= nacl_buf
->nacl_abi_st_size
;
54 buf
->st_blksize
= nacl_buf
->nacl_abi_st_blksize
;
55 buf
->st_blocks
= nacl_buf
->nacl_abi_st_blocks
;
56 buf
->st_atime
= nacl_buf
->nacl_abi_st_atime
;
57 buf
->st_mtime
= nacl_buf
->nacl_abi_st_mtime
;
58 buf
->st_ctime
= nacl_buf
->nacl_abi_st_ctime
;
63 // From native_client/src/trusted/service_runtime/include/sys/dirent.h
65 #ifndef nacl_abi___ino_t_defined
66 #define nacl_abi___ino_t_defined
67 typedef int64_t nacl_abi___ino_t
;
68 typedef nacl_abi___ino_t nacl_abi_ino_t
;
71 #ifndef nacl_abi___off_t_defined
72 #define nacl_abi___off_t_defined
73 typedef int64_t nacl_abi__off_t
;
74 typedef nacl_abi__off_t nacl_abi_off_t
;
77 /* We need a way to define the maximum size of a name. */
80 # define MAXNAMLEN NAME_MAX
82 # define MAXNAMLEN 255
86 struct nacl_abi_dirent
{
87 nacl_abi_ino_t nacl_abi_d_ino
;
88 nacl_abi_off_t nacl_abi_d_off
;
89 uint16_t nacl_abi_d_reclen
;
90 char nacl_abi_d_name
[MAXNAMLEN
+ 1];
93 static const int d_name_shift
= offsetof (dirent
, d_name
) -
94 offsetof (struct nacl_abi_dirent
, nacl_abi_d_name
);
98 // Macro to get the REAL function pointer
99 #define REAL(name) __nacl_irt_##name##_real
101 // Macro to get the WRAP function
102 #define WRAP(name) __nacl_irt_##name##_wrap
104 // Declare REAL function pointer.
105 #define DECLARE_REAL_PTR(name) typeof(__nacl_irt_##name) REAL(name);
107 // Assign the REAL function pointer.
108 #define ASSIGN_REAL_PTR(name) REAL(name) = __nacl_irt_##name;
110 // Switch IRT's pointer to the REAL pointer
111 #define USE_REAL(name) __nacl_irt_##name = (typeof(__nacl_irt_##name))REAL(name)
113 // Switch IRT's pointer to the WRAP function
114 #define USE_WRAP(name) __nacl_irt_##name = (typeof(__nacl_irt_##name))WRAP(name)
116 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \
145 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR
);
147 int WRAP(chdir
)(const char* pathname
) {
148 ERRNO_RTN(ki_chdir(pathname
));
151 int WRAP(close
)(int fd
) {
152 ERRNO_RTN(ki_close(fd
));
155 int WRAP(dup
)(int fd
, int* newfd
) NOTHROW
{
160 int WRAP(dup2
)(int fd
, int newfd
) NOTHROW
{
161 ERRNO_RTN(ki_dup2(fd
, newfd
));
164 void WRAP(exit
)(int status
) {
168 int WRAP(fchdir
)(int fd
) NOTHROW
{
169 ERRNO_RTN(ki_fchdir(fd
));
172 int WRAP(fchmod
)(int fd
, mode_t mode
) NOTHROW
{
173 ERRNO_RTN(ki_fchmod(fd
, mode
));
176 int WRAP(fdatasync
)(int fd
) NOTHROW
{
177 ERRNO_RTN(ki_fdatasync(fd
));
180 int WRAP(fstat
)(int fd
, struct nacl_abi_stat
* nacl_buf
) {
182 memset(&buf
, 0, sizeof(struct stat
));
183 int res
= ki_fstat(fd
, &buf
);
184 RTN_ERRNO_IF(res
< 0);
185 stat_to_nacl_stat(&buf
, nacl_buf
);
189 int WRAP(fsync
)(int fd
) NOTHROW
{
190 ERRNO_RTN(ki_fsync(fd
));
193 int WRAP(getcwd
)(char* buf
, size_t size
) {
194 RTN_ERRNO_IF(ki_getcwd(buf
, size
) == NULL
);
198 int WRAP(getdents
)(int fd
, dirent
* nacl_buf
, size_t nacl_count
, size_t* nread
) {
200 // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
201 // nacl_abi_dirent(s) are smaller than dirent(s), so nacl_count bytes buffer
203 char* buf
= (char*)alloca(nacl_count
);
207 count
= ki_getdents(fd
, buf
, nacl_count
);
208 RTN_ERRNO_IF(count
< 0);
210 while (offset
< count
) {
211 dirent
* d
= (dirent
*)(buf
+ offset
);
212 nacl_abi_dirent
* nacl_d
= (nacl_abi_dirent
*)((char*)nacl_buf
+ nacl_offset
);
213 nacl_d
->nacl_abi_d_ino
= d
->d_ino
;
214 nacl_d
->nacl_abi_d_off
= d
->d_off
;
215 nacl_d
->nacl_abi_d_reclen
= d
->d_reclen
- d_name_shift
;
216 size_t d_name_len
= d
->d_reclen
- offsetof(dirent
, d_name
);
217 memcpy(nacl_d
->nacl_abi_d_name
, d
->d_name
, d_name_len
);
219 offset
+= d
->d_reclen
;
220 nacl_offset
+= nacl_d
->nacl_abi_d_reclen
;
223 *nread
= nacl_offset
;
227 int WRAP(isatty
)(int fd
, int* result
) {
228 *result
= ki_isatty(fd
);
229 RTN_ERRNO_IF(*result
== 0);
233 int WRAP(lstat
)(const char* path
, struct nacl_abi_stat
* nacl_buf
) {
235 memset(&buf
, 0, sizeof(struct stat
));
236 int res
= ki_lstat(path
, &buf
);
237 RTN_ERRNO_IF(res
< 0);
238 stat_to_nacl_stat(&buf
, nacl_buf
);
242 int WRAP(mkdir
)(const char* pathname
, mode_t mode
) {
243 ERRNO_RTN(ki_mkdir(pathname
, mode
));
246 int WRAP(mmap
)(void** addr
,
252 if (flags
& MAP_ANONYMOUS
)
253 return REAL(mmap
)(addr
, length
, prot
, flags
, fd
, offset
);
255 *addr
= ki_mmap(*addr
, length
, prot
, flags
, fd
, offset
);
256 RTN_ERRNO_IF(*addr
== (void*)-1)
260 int WRAP(munmap
)(void* addr
, size_t length
) {
261 // Always let the real munmap run on the address range. It is not an error if
262 // there are no mapped pages in that range.
263 ki_munmap(addr
, length
);
264 return REAL(munmap
)(addr
, length
);
267 int WRAP(open
)(const char* pathname
, int oflag
, mode_t cmode
, int* newfd
) {
268 *newfd
= ki_open(pathname
, oflag
);
272 int WRAP(open_resource
)(const char* file
, int* fd
) {
273 *fd
= ki_open_resource(file
);
277 int WRAP(poll
)(struct pollfd
* fds
, nfds_t nfds
, int timeout
, int* count
) {
278 *count
= ki_poll(fds
, nfds
, timeout
);
282 int WRAP(read
)(int fd
, void* buf
, size_t count
, size_t* nread
) {
283 ssize_t signed_nread
= ki_read(fd
, buf
, count
);
284 *nread
= static_cast<size_t>(signed_nread
);
285 ERRNO_RTN(signed_nread
);
288 int WRAP(readlink
)(const char* path
, char* buf
, size_t count
, size_t* nread
) {
289 ssize_t signed_nread
= ki_readlink(path
, buf
, count
);
290 *nread
= static_cast<size_t>(signed_nread
);
291 ERRNO_RTN(signed_nread
);
294 int WRAP(rmdir
)(const char* pathname
) {
295 ERRNO_RTN(ki_rmdir(pathname
));
298 int WRAP(seek
)(int fd
, off64_t offset
, int whence
, int64_t* new_offset
) {
299 *new_offset
= ki_lseek(fd
, offset
, whence
);
300 ERRNO_RTN(*new_offset
);
303 int WRAP(select
)(int nfds
,
307 struct timeval
* timeout
,
309 *count
= ki_select(nfds
, readfds
, writefds
, exceptfds
, timeout
);
313 int WRAP(stat
)(const char* pathname
, struct nacl_abi_stat
* nacl_buf
) {
315 memset(&buf
, 0, sizeof(struct stat
));
316 int res
= ki_stat(pathname
, &buf
);
317 RTN_ERRNO_IF(res
< 0);
318 stat_to_nacl_stat(&buf
, nacl_buf
);
322 int WRAP(truncate
)(const char* name
, int64_t len
) {
323 ERRNO_RTN(ki_truncate(name
, len
));
326 int WRAP(write
)(int fd
, const void* buf
, size_t count
, size_t* nwrote
) {
327 ssize_t signed_nwrote
= ki_write(fd
, buf
, count
);
328 *nwrote
= static_cast<size_t>(signed_nwrote
);
329 ERRNO_RTN(signed_nwrote
);
332 static void assign_real_pointers() {
333 static bool assigned
= false;
335 EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR
)
340 #define CHECK_REAL(func) \
342 assign_real_pointers();
344 #define CHECK_REAL_NOSYS(func) \
349 // "real" functions, i.e. the unwrapped original functions.
351 int _real_close(int fd
) {
353 return REAL(close
)(fd
);
356 void _real_exit(int status
) {
360 int _real_fchdir(int fd
) {
362 return REAL(fchdir
)(fd
);
365 int _real_fchmod(int fd
, mode_t mode
) {
367 return REAL(fchmod
)(fd
, mode
);
370 int _real_fdatasync(int fd
) {
371 CHECK_REAL(fdatasync
);
372 return REAL(fdatasync
)(fd
);
375 int _real_fstat(int fd
, struct stat
* buf
) {
376 struct nacl_abi_stat st
;
379 int err
= REAL(fstat
)(fd
, (struct stat
*)&st
);
385 nacl_stat_to_stat(&st
, buf
);
389 int _real_fsync(int fd
) {
391 return REAL(fsync
)(fd
);
394 int _real_getdents(int fd
, void* buf
, size_t count
, size_t* nread
) {
395 // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
396 // See WRAP(getdents) above.
397 char* nacl_buf
= (char*)alloca(count
);
399 size_t nacl_offset
= 0;
401 CHECK_REAL(getdents
);
402 int err
= REAL(getdents
)(fd
, (dirent
*)nacl_buf
, count
, &nacl_nread
);
406 while (nacl_offset
< nacl_nread
) {
407 dirent
* d
= (dirent
*)((char*)buf
+ offset
);
408 nacl_abi_dirent
* nacl_d
= (nacl_abi_dirent
*)(nacl_buf
+ nacl_offset
);
409 d
->d_ino
= nacl_d
->nacl_abi_d_ino
;
410 d
->d_off
= nacl_d
->nacl_abi_d_off
;
411 d
->d_reclen
= nacl_d
->nacl_abi_d_reclen
+ d_name_shift
;
413 nacl_d
->nacl_abi_d_reclen
- offsetof(nacl_abi_dirent
, nacl_abi_d_name
);
414 memcpy(d
->d_name
, nacl_d
->nacl_abi_d_name
, d_name_len
);
416 offset
+= d
->d_reclen
;
417 offset
+= nacl_d
->nacl_abi_d_reclen
;
424 int _real_isatty(int fd
, int* result
) {
425 *result
= isatty(fd
);
426 return *result
? 0 : -1;
429 int _real_lseek(int fd
, int64_t offset
, int whence
, int64_t* new_offset
) {
431 nacl_abi_off_t nacl_new_offs
;
432 int ret
= REAL(seek
)(fd
, offset
, whence
, &nacl_new_offs
);
433 *new_offset
= static_cast<off_t
>(nacl_new_offs
);
437 int _real_lstat(const char* path
, struct stat
* buf
) {
438 struct nacl_abi_stat st
;
441 int err
= REAL(lstat
)(path
, (struct stat
*)&st
);
447 nacl_stat_to_stat(&st
, buf
);
451 int _real_mkdir(const char* pathname
, mode_t mode
) {
453 return REAL(mkdir
)(pathname
, mode
);
456 int _real_mmap(void** addr
,
463 return REAL(mmap
)(addr
, length
, prot
, flags
, fd
, offset
);
466 int _real_munmap(void* addr
, size_t length
) {
468 return REAL(munmap
)(addr
, length
);
471 int _real_open(const char* pathname
, int oflag
, mode_t cmode
, int* newfd
) {
473 return REAL(open
)(pathname
, oflag
, cmode
, newfd
);
476 int _real_open_resource(const char* file
, int* fd
) {
477 CHECK_REAL(open_resource
);
478 return REAL(open_resource
)(file
, fd
);
481 int _real_read(int fd
, void* buf
, size_t count
, size_t* nread
) {
483 return REAL(read
)(fd
, buf
, count
, nread
);
486 int _real_readlink(const char* path
, char* buf
, size_t count
, size_t* nread
) {
487 CHECK_REAL(readlink
);
488 return REAL(readlink
)(path
, buf
, count
, nread
);
491 int _real_rmdir(const char* pathname
) {
493 return REAL(rmdir
)(pathname
);
496 int _real_truncate(const char* pathname
, int64_t len
) {
497 CHECK_REAL(truncate
);
498 return REAL(truncate
)(pathname
, len
);
501 int _real_write(int fd
, const void* buf
, size_t count
, size_t* nwrote
) {
503 return REAL(write
)(fd
, buf
, count
, nwrote
);
506 int _real_getcwd(char* pathname
, size_t len
) {
507 CHECK_REAL_NOSYS(getcwd
);
508 return REAL(getcwd
)(pathname
, len
);
511 static bool s_wrapped
= false;
513 void kernel_wrap_init() {
515 assign_real_pointers();
516 EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP
)
521 void kernel_wrap_uninit() {
523 EXPAND_SYMBOL_LIST_OPERATION(USE_REAL
)
530 #endif // defined(__native_client__) && defined(__BIONIC__)