Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 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. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 4 | |
| 5 | #include <sys/types.h> // Include something that will define __GLIBC__. |
| 6 | |
| 7 | // The entire file is wrapped in this #if. We do this so this .cc file can be |
| 8 | // compiled, even on a non-glibc build. |
| 9 | #if defined(__native_client__) && defined(__GLIBC__) |
| 10 | |
| 11 | #include "nacl_io/kernel_wrap.h" |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 12 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 13 | #include <alloca.h> |
| 14 | #include <dirent.h> |
| 15 | #include <errno.h> |
| 16 | #include <irt.h> |
| 17 | #include <irt_syscalls.h> |
| 18 | #include <nacl_stat.h> |
| 19 | #include <string.h> |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 20 | #include <sys/stat.h> |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 21 | #include <sys/time.h> |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 22 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 23 | #include "nacl_io/kernel_intercept.h" |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 24 | #include "nacl_io/osmman.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 25 | |
| 26 | |
| 27 | namespace { |
| 28 | |
| 29 | void stat_to_nacl_stat(const struct stat* buf, nacl_abi_stat* nacl_buf) { |
| 30 | memset(nacl_buf, 0, sizeof(struct nacl_abi_stat)); |
| 31 | nacl_buf->nacl_abi_st_dev = buf->st_dev; |
| 32 | nacl_buf->nacl_abi_st_ino = buf->st_ino; |
| 33 | nacl_buf->nacl_abi_st_mode = buf->st_mode; |
| 34 | nacl_buf->nacl_abi_st_nlink = buf->st_nlink; |
| 35 | nacl_buf->nacl_abi_st_uid = buf->st_uid; |
| 36 | nacl_buf->nacl_abi_st_gid = buf->st_gid; |
| 37 | nacl_buf->nacl_abi_st_rdev = buf->st_rdev; |
| 38 | nacl_buf->nacl_abi_st_size = buf->st_size; |
| 39 | nacl_buf->nacl_abi_st_blksize = buf->st_blksize; |
| 40 | nacl_buf->nacl_abi_st_blocks = buf->st_blocks; |
| 41 | nacl_buf->nacl_abi_st_atime = buf->st_atime; |
| 42 | nacl_buf->nacl_abi_st_mtime = buf->st_mtime; |
| 43 | nacl_buf->nacl_abi_st_ctime = buf->st_ctime; |
| 44 | } |
| 45 | |
| 46 | void nacl_stat_to_stat(const nacl_abi_stat* nacl_buf, struct stat* buf) { |
| 47 | memset(buf, 0, sizeof(struct stat)); |
| 48 | buf->st_dev = nacl_buf->nacl_abi_st_dev; |
| 49 | buf->st_ino = nacl_buf->nacl_abi_st_ino; |
| 50 | buf->st_mode = nacl_buf->nacl_abi_st_mode; |
| 51 | buf->st_nlink = nacl_buf->nacl_abi_st_nlink; |
| 52 | buf->st_uid = nacl_buf->nacl_abi_st_uid; |
| 53 | buf->st_gid = nacl_buf->nacl_abi_st_gid; |
| 54 | buf->st_rdev = nacl_buf->nacl_abi_st_rdev; |
| 55 | buf->st_size = nacl_buf->nacl_abi_st_size ; |
| 56 | buf->st_blksize = nacl_buf->nacl_abi_st_blksize; |
| 57 | buf->st_blocks = nacl_buf->nacl_abi_st_blocks; |
| 58 | buf->st_atime = nacl_buf->nacl_abi_st_atime; |
| 59 | buf->st_mtime = nacl_buf->nacl_abi_st_mtime; |
| 60 | buf->st_ctime = nacl_buf->nacl_abi_st_ctime; |
| 61 | } |
| 62 | |
| 63 | } // namespace |
| 64 | |
| 65 | // From native_client/src/trusted/service_runtime/include/sys/dirent.h |
| 66 | |
| 67 | #ifndef nacl_abi___ino_t_defined |
| 68 | #define nacl_abi___ino_t_defined |
| 69 | typedef int64_t nacl_abi___ino_t; |
| 70 | typedef nacl_abi___ino_t nacl_abi_ino_t; |
| 71 | #endif |
| 72 | |
| 73 | #ifndef nacl_abi___off_t_defined |
| 74 | #define nacl_abi___off_t_defined |
| 75 | typedef int64_t nacl_abi__off_t; |
| 76 | typedef nacl_abi__off_t nacl_abi_off_t; |
| 77 | #endif |
| 78 | |
| 79 | /* We need a way to define the maximum size of a name. */ |
| 80 | #ifndef MAXNAMLEN |
| 81 | # ifdef NAME_MAX |
| 82 | # define MAXNAMLEN NAME_MAX |
| 83 | # else |
| 84 | # define MAXNAMLEN 255 |
| 85 | # endif |
| 86 | #endif |
| 87 | |
| 88 | struct nacl_abi_dirent { |
| 89 | nacl_abi_ino_t nacl_abi_d_ino; |
| 90 | nacl_abi_off_t nacl_abi_d_off; |
| 91 | uint16_t nacl_abi_d_reclen; |
| 92 | char nacl_abi_d_name[MAXNAMLEN + 1]; |
| 93 | }; |
| 94 | |
| 95 | static const int d_name_shift = offsetof (dirent, d_name) - |
| 96 | offsetof (struct nacl_abi_dirent, nacl_abi_d_name); |
| 97 | |
| 98 | EXTERN_C_BEGIN |
| 99 | |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 100 | // Macro to get the REAL function pointer |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 101 | #define REAL(name) __nacl_irt_##name##_real |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 102 | |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 103 | // Macro to get the WRAP function |
| 104 | #define WRAP(name) __nacl_irt_##name##_wrap |
| 105 | |
| 106 | // Declare REAL function pointer and assign it the REAL function. |
| 107 | #define DECLARE_REAL_PTR(name) \ |
| 108 | typeof(__nacl_irt_##name) REAL(name) = __nacl_irt_##name; |
| 109 | |
| 110 | // Switch IRT's pointer to the REAL pointer |
| 111 | #define USE_REAL(name) \ |
| 112 | __nacl_irt_##name = (typeof(__nacl_irt_##name)) REAL(name) |
| 113 | |
| 114 | // Switch IRT's pointer to the WRAP function |
| 115 | #define USE_WRAP(name) \ |
| 116 | __nacl_irt_##name = (typeof(__nacl_irt_##name)) WRAP(name) |
| 117 | |
| 118 | |
| 119 | #define EXPAND_SYMBOL_LIST_OPERATION(OP) \ |
| 120 | OP(chdir); \ |
| 121 | OP(close); \ |
| 122 | OP(dup); \ |
| 123 | OP(dup2); \ |
| 124 | OP(fstat); \ |
| 125 | OP(getcwd); \ |
| 126 | OP(getdents); \ |
| 127 | OP(mkdir); \ |
| 128 | OP(open); \ |
Ben Murdoch | 3240926 | 2013-08-07 11:04:47 +0100 | [diff] [blame] | 129 | OP(poll);\ |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 130 | OP(read); \ |
| 131 | OP(rmdir); \ |
| 132 | OP(seek); \ |
| 133 | OP(stat); \ |
Ben Murdoch | 3240926 | 2013-08-07 11:04:47 +0100 | [diff] [blame] | 134 | OP(select); \ |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 135 | OP(write); \ |
| 136 | OP(mmap); \ |
| 137 | OP(munmap); \ |
| 138 | OP(open_resource); |
| 139 | |
| 140 | EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 141 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 142 | int WRAP(chdir) (const char* pathname) { |
| 143 | return (ki_chdir(pathname)) ? errno : 0; |
| 144 | } |
| 145 | |
| 146 | int WRAP(close)(int fd) { |
| 147 | return (ki_close(fd) < 0) ? errno : 0; |
| 148 | } |
| 149 | |
| 150 | int WRAP(dup)(int fd, int* newfd) NOTHROW { |
| 151 | *newfd = ki_dup(fd); |
| 152 | return (*newfd < 0) ? errno : 0; |
| 153 | } |
| 154 | |
| 155 | int WRAP(dup2)(int fd, int newfd) NOTHROW { |
| 156 | return (ki_dup2(fd, newfd) < 0) ? errno : 0; |
| 157 | } |
| 158 | |
| 159 | int WRAP(fstat)(int fd, struct nacl_abi_stat *nacl_buf) { |
| 160 | struct stat buf; |
| 161 | memset(&buf, 0, sizeof(struct stat)); |
| 162 | int res = ki_fstat(fd, &buf); |
| 163 | if (res < 0) |
| 164 | return errno; |
| 165 | stat_to_nacl_stat(&buf, nacl_buf); |
| 166 | return 0; |
| 167 | } |
| 168 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 169 | char* WRAP(getcwd)(char* buf, size_t size) { |
| 170 | return ki_getcwd(buf, size); |
| 171 | } |
| 172 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 173 | int WRAP(getdents)(int fd, dirent* nacl_buf, size_t nacl_count, size_t *nread) { |
| 174 | int nacl_offset = 0; |
| 175 | // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s). |
| 176 | // nacl_abi_dirent(s) are smaller than dirent(s), so nacl_count bytes buffer |
| 177 | // is enough |
| 178 | char* buf = (char*)alloca(nacl_count); |
| 179 | int offset = 0; |
| 180 | int count; |
| 181 | |
| 182 | count = ki_getdents(fd, buf, nacl_count); |
| 183 | if (count < 0) |
| 184 | return errno; |
| 185 | |
| 186 | while (offset < count) { |
| 187 | dirent* d = (dirent*)(buf + offset); |
| 188 | nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)((char*)nacl_buf + nacl_offset); |
| 189 | nacl_d->nacl_abi_d_ino = d->d_ino; |
| 190 | nacl_d->nacl_abi_d_off = d->d_off; |
| 191 | nacl_d->nacl_abi_d_reclen = d->d_reclen - d_name_shift; |
| 192 | size_t d_name_len = d->d_reclen - offsetof(dirent, d_name); |
| 193 | memcpy(nacl_d->nacl_abi_d_name, d->d_name, d_name_len); |
| 194 | |
| 195 | offset += d->d_reclen; |
| 196 | nacl_offset += nacl_d->nacl_abi_d_reclen; |
| 197 | } |
| 198 | |
| 199 | *nread = nacl_offset; |
| 200 | return 0; |
| 201 | } |
| 202 | |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 203 | int WRAP(mkdir)(const char* pathname, mode_t mode) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 204 | return (ki_mkdir(pathname, mode)) ? errno : 0; |
| 205 | } |
| 206 | |
| 207 | int WRAP(mmap)(void** addr, size_t length, int prot, int flags, int fd, |
| 208 | off_t offset) { |
| 209 | if (flags & MAP_ANONYMOUS) |
| 210 | return REAL(mmap)(addr, length, prot, flags, fd, offset); |
| 211 | |
| 212 | *addr = ki_mmap(*addr, length, prot, flags, fd, offset); |
| 213 | return *addr == (void*)-1 ? errno : 0; |
| 214 | } |
| 215 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 216 | int WRAP(munmap)(void* addr, size_t length) { |
| 217 | // Always let the real munmap run on the address range. It is not an error if |
| 218 | // there are no mapped pages in that range. |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 219 | ki_munmap(addr, length); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 220 | return REAL(munmap)(addr, length); |
| 221 | } |
| 222 | |
| 223 | int WRAP(open)(const char* pathname, int oflag, mode_t cmode, int* newfd) { |
| 224 | *newfd = ki_open(pathname, oflag); |
| 225 | return (*newfd < 0) ? errno : 0; |
| 226 | } |
| 227 | |
| 228 | int WRAP(open_resource)(const char* file, int* fd) { |
| 229 | *fd = ki_open_resource(file); |
| 230 | return (*fd < 0) ? errno : 0; |
| 231 | } |
| 232 | |
Ben Murdoch | 3240926 | 2013-08-07 11:04:47 +0100 | [diff] [blame] | 233 | int WRAP(poll)(struct pollfd *fds, nfds_t nfds, int timeout, int* count) { |
| 234 | *count = ki_poll(fds, nfds, timeout); |
| 235 | return (*count < 0) ? errno : 0; |
| 236 | |
| 237 | } |
| 238 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 239 | int WRAP(read)(int fd, void *buf, size_t count, size_t *nread) { |
| 240 | if (!ki_is_initialized()) |
| 241 | return REAL(read)(fd, buf, count, nread); |
| 242 | |
| 243 | ssize_t signed_nread = ki_read(fd, buf, count); |
| 244 | *nread = static_cast<size_t>(signed_nread); |
| 245 | return (signed_nread < 0) ? errno : 0; |
| 246 | } |
| 247 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 248 | int WRAP(rmdir)(const char* pathname) { |
| 249 | return (ki_rmdir(pathname) < 0) ? errno : 0; |
| 250 | } |
| 251 | |
| 252 | int WRAP(seek)(int fd, off_t offset, int whence, off_t* new_offset) { |
| 253 | *new_offset = ki_lseek(fd, offset, whence); |
| 254 | return (*new_offset < 0) ? errno : 0; |
| 255 | } |
| 256 | |
Ben Murdoch | 3240926 | 2013-08-07 11:04:47 +0100 | [diff] [blame] | 257 | int WRAP(select)(int nfds, fd_set* readfds, fd_set* writefds, |
| 258 | fd_set* exceptfds, struct timeval* timeout, int* count) { |
| 259 | *count = ki_select(nfds, readfds, writefds, exceptfds, timeout); |
| 260 | return (*count < 0) ? errno : 0; |
| 261 | } |
| 262 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 263 | int WRAP(stat)(const char *pathname, struct nacl_abi_stat *nacl_buf) { |
| 264 | struct stat buf; |
| 265 | memset(&buf, 0, sizeof(struct stat)); |
| 266 | int res = ki_stat(pathname, &buf); |
| 267 | if (res < 0) |
| 268 | return errno; |
| 269 | stat_to_nacl_stat(&buf, nacl_buf); |
| 270 | return 0; |
| 271 | } |
| 272 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 273 | int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 274 | if (!ki_is_initialized()) |
| 275 | return REAL(write)(fd, buf, count, nwrote); |
| 276 | |
| 277 | ssize_t signed_nwrote = ki_write(fd, buf, count); |
| 278 | *nwrote = static_cast<size_t>(signed_nwrote); |
| 279 | return (signed_nwrote < 0) ? errno : 0; |
| 280 | } |
| 281 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 282 | // Socket functions |
| 283 | int accept(int fd, struct sockaddr* addr, socklen_t* len) { |
| 284 | return ki_accept(fd, addr, len); |
| 285 | } |
| 286 | |
| 287 | int bind(int fd, const struct sockaddr* addr, socklen_t len) { |
| 288 | return ki_bind(fd, addr, len); |
| 289 | } |
| 290 | |
| 291 | int connect(int fd, const struct sockaddr* addr, socklen_t len) { |
| 292 | return ki_connect(fd, addr, len); |
| 293 | } |
| 294 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 295 | struct hostent* gethostbyname(const char* name) { |
| 296 | return ki_gethostbyname(name); |
| 297 | } |
| 298 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 299 | int getpeername(int fd, struct sockaddr* addr, socklen_t* len) { |
| 300 | return ki_getpeername(fd, addr, len); |
| 301 | } |
| 302 | |
| 303 | int getsockname(int fd, struct sockaddr* addr, socklen_t* len) { |
| 304 | return ki_getsockname(fd, addr, len); |
| 305 | } |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 306 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 307 | int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) { |
| 308 | return ki_getsockopt(fd, lvl, optname, optval, len); |
| 309 | } |
| 310 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 311 | void herror(const char *s) { |
| 312 | return ki_herror(s); |
| 313 | } |
| 314 | |
| 315 | const char *hstrerror(int err) { |
| 316 | return ki_hstrerror(err); |
| 317 | } |
| 318 | |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 319 | int listen(int fd, int backlog) { |
| 320 | return ki_listen(fd, backlog); |
| 321 | } |
| 322 | |
| 323 | ssize_t recv(int fd, void* buf, size_t len, int flags) { |
| 324 | return ki_recv(fd, buf, len, flags); |
| 325 | } |
| 326 | |
| 327 | ssize_t recvfrom(int fd, void* buf, size_t len, int flags, |
| 328 | struct sockaddr* addr, socklen_t* addrlen) { |
| 329 | return ki_recvfrom(fd, buf, len, flags, addr, addrlen); |
| 330 | } |
| 331 | |
| 332 | ssize_t recvmsg(int fd, struct msghdr* msg, int flags) { |
| 333 | return ki_recvmsg(fd, msg, flags); |
| 334 | } |
| 335 | |
| 336 | ssize_t send(int fd, const void* buf, size_t len, int flags) { |
| 337 | return ki_send(fd, buf, len, flags); |
| 338 | } |
| 339 | |
| 340 | ssize_t sendto(int fd, const void* buf, size_t len, int flags, |
| 341 | const struct sockaddr* addr, socklen_t addrlen) { |
| 342 | return ki_sendto(fd, buf, len, flags, addr, addrlen); |
| 343 | } |
| 344 | |
| 345 | ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) { |
| 346 | return ki_sendmsg(fd, msg, flags); |
| 347 | } |
| 348 | |
| 349 | int setsockopt(int fd, int lvl, int optname, const void* optval, |
| 350 | socklen_t len) { |
| 351 | return ki_setsockopt(fd, lvl, optname, optval, len); |
| 352 | } |
| 353 | |
| 354 | int shutdown(int fd, int how) { |
| 355 | return ki_shutdown(fd, how); |
| 356 | } |
| 357 | |
| 358 | int socket(int domain, int type, int protocol) { |
| 359 | return ki_socket(domain, type, protocol); |
| 360 | } |
| 361 | |
| 362 | int socketpair(int domain, int type, int protocol, int* sv) { |
| 363 | return ki_socketpair(domain, type, protocol, sv); |
| 364 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 365 | |
| 366 | // "real" functions, i.e. the unwrapped original functions. |
| 367 | |
| 368 | int _real_close(int fd) { |
| 369 | return REAL(close)(fd); |
| 370 | } |
| 371 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 372 | int _real_fstat(int fd, struct stat* buf) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 373 | struct nacl_abi_stat st; |
| 374 | int err = REAL(fstat)(fd, &st); |
| 375 | if (err) { |
| 376 | errno = err; |
| 377 | return -1; |
| 378 | } |
| 379 | |
| 380 | nacl_stat_to_stat(&st, buf); |
| 381 | return 0; |
| 382 | } |
| 383 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 384 | int _real_getdents(int fd, void* buf, size_t count, size_t* nread) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 385 | // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s). |
| 386 | // See WRAP(getdents) above. |
| 387 | char* nacl_buf = (char*)alloca(count); |
| 388 | size_t offset = 0; |
| 389 | size_t nacl_offset = 0; |
| 390 | size_t nacl_nread; |
| 391 | int err = REAL(getdents)(fd, (dirent*)nacl_buf, count, &nacl_nread); |
| 392 | if (err) |
| 393 | return err; |
| 394 | |
| 395 | while (nacl_offset < nacl_nread) { |
| 396 | dirent* d = (dirent*)((char*)buf + offset); |
| 397 | nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)(nacl_buf + nacl_offset); |
| 398 | d->d_ino = nacl_d->nacl_abi_d_ino; |
| 399 | d->d_off = nacl_d->nacl_abi_d_off; |
| 400 | d->d_reclen = nacl_d->nacl_abi_d_reclen + d_name_shift; |
| 401 | size_t d_name_len = nacl_d->nacl_abi_d_reclen - |
| 402 | offsetof(nacl_abi_dirent, nacl_abi_d_name); |
| 403 | memcpy(d->d_name, nacl_d->nacl_abi_d_name, d_name_len); |
| 404 | |
| 405 | offset += d->d_reclen; |
| 406 | offset += nacl_d->nacl_abi_d_reclen; |
| 407 | } |
| 408 | |
| 409 | *nread = offset; |
| 410 | return 0; |
| 411 | } |
| 412 | |
| 413 | int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset) { |
| 414 | return REAL(seek)(fd, offset, whence, new_offset); |
| 415 | } |
| 416 | |
| 417 | int _real_mkdir(const char* pathname, mode_t mode) { |
| 418 | return REAL(mkdir)(pathname, mode); |
| 419 | } |
| 420 | |
| 421 | int _real_mmap(void** addr, size_t length, int prot, int flags, int fd, |
| 422 | off_t offset) { |
| 423 | return REAL(mmap)(addr, length, prot, flags, fd, offset); |
| 424 | } |
| 425 | |
| 426 | int _real_munmap(void* addr, size_t length) { |
| 427 | return REAL(munmap)(addr, length); |
| 428 | } |
| 429 | |
| 430 | int _real_open(const char* pathname, int oflag, mode_t cmode, int* newfd) { |
| 431 | return REAL(open)(pathname, oflag, cmode, newfd); |
| 432 | } |
| 433 | |
| 434 | int _real_open_resource(const char* file, int* fd) { |
| 435 | return REAL(open_resource)(file, fd); |
| 436 | } |
| 437 | |
| 438 | int _real_read(int fd, void *buf, size_t count, size_t *nread) { |
| 439 | return REAL(read)(fd, buf, count, nread); |
| 440 | } |
| 441 | |
| 442 | int _real_rmdir(const char* pathname) { |
| 443 | return REAL(rmdir)(pathname); |
| 444 | } |
| 445 | |
| 446 | int _real_write(int fd, const void *buf, size_t count, size_t *nwrote) { |
| 447 | return REAL(write)(fd, buf, count, nwrote); |
| 448 | } |
| 449 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 450 | uint64_t usec_since_epoch() { |
| 451 | struct timeval tv; |
| 452 | gettimeofday(&tv, NULL); |
| 453 | return tv.tv_usec + (tv.tv_sec * 1000000); |
| 454 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 455 | |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 456 | static bool s_wrapped = false; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 457 | void kernel_wrap_init() { |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 458 | if (!s_wrapped) { |
| 459 | EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP) |
| 460 | s_wrapped = true; |
| 461 | } |
| 462 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 463 | |
Ben Murdoch | 58e6fbe | 2013-07-26 10:20:38 +0100 | [diff] [blame] | 464 | void kernel_wrap_uninit() { |
| 465 | if (s_wrapped) { |
| 466 | EXPAND_SYMBOL_LIST_OPERATION(USE_REAL) |
| 467 | s_wrapped = false; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 468 | } |
| 469 | } |
| 470 | |
| 471 | EXTERN_C_END |
| 472 | |
| 473 | |
| 474 | #endif // defined(__native_client__) && defined(__GLIBC__) |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 475 | |