Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / native_client_sdk / src / libraries / nacl_io / kernel_wrap_irt_ext.c
blobac15469c1b5e3178399ee714afe1b323d702fde5
1 /* Copyright 2014 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 /* NACL_IO_IRT_EXT is defined in this header */
6 #include "nacl_io/kernel_wrap.h"
8 /*
9 * The entire file is wrapped in this #if. We do this so this .c file can
10 * always be compiled.
12 #if defined(NACL_IO_IRT_EXT)
14 #include <assert.h>
15 #include <errno.h>
16 #include <irt.h>
17 #include <irt_dev.h>
18 #include <irt_extension.h>
19 #include <stdbool.h>
20 #include <string.h>
21 #include <sys/mman.h>
23 #include "nacl_io/kernel_intercept.h"
24 #include "nacl_io/log.h"
25 #include "nacl_io/nacl_abi_types.h"
28 * The following macros are used to interfact with IRT interfaces.
30 /* This macro defines an interfact structure, use as a regular type. */
31 #define NACL_IRT_INTERFACE(interface_type) \
32 struct nacl_io_##interface_type { \
33 const char *query_string; \
34 bool queried; \
35 bool initialized; \
36 struct interface_type interface; \
39 /* This macro unconditionally initializes an interface (do not use directly). */
40 #define INIT_INTERFACE_BARE(interface_struct) \
41 if (!interface_struct.queried) { \
42 const size_t bytes __attribute__((unused)) = \
43 nacl_interface_query(interface_struct.query_string, \
44 &interface_struct.interface, \
45 sizeof(interface_struct.interface)); \
46 interface_struct.queried = true; \
47 interface_struct.initialized = \
48 (bytes == sizeof(interface_struct.interface)); \
51 /* This macro initializes an interface and does not handle errors. */
52 #define INIT_INTERFACE(interface_struct) \
53 do { \
54 INIT_INTERFACE_BARE(interface_struct); \
55 } while (false)
57 /* This macro initializes an interface and returns ENOSYS on failure. */
58 #define INIT_INTERFACE_ENOSYS(interface_struct) \
59 do { \
60 INIT_INTERFACE_BARE(interface_struct); \
61 if (!interface_struct.initialized) \
62 return ENOSYS; \
63 } while (false)
65 /* This macro initializes an interface and asserts on failure. */
66 #define INIT_INTERFACE_ASSERT(interface_struct) \
67 do { \
68 INIT_INTERFACE_BARE(interface_struct); \
69 assert(interface_struct.initialized); \
70 } while (false)
72 /* This macro supplies an IRT Extension interface and asserts on failure. */
73 #define EXT_SUPPLY_INTERFACE_ASSERT(interface_struct, supplied_struct) \
74 do { \
75 const size_t bytes __attribute__((unused)) = \
76 nacl_interface_ext_supply(interface_struct.query_string, \
77 &supplied_struct, \
78 sizeof(supplied_struct)); \
79 assert(bytes == sizeof(supplied_struct)); \
80 } while (false)
83 void stat_to_nacl_stat(const struct stat* buf, nacl_irt_stat_t* nacl_buf) {
84 memset(nacl_buf, 0, sizeof(struct nacl_abi_stat));
85 nacl_buf->nacl_abi_st_dev = buf->st_dev;
86 nacl_buf->nacl_abi_st_ino = buf->st_ino;
87 nacl_buf->nacl_abi_st_mode = buf->st_mode;
88 nacl_buf->nacl_abi_st_nlink = buf->st_nlink;
89 nacl_buf->nacl_abi_st_uid = buf->st_uid;
90 nacl_buf->nacl_abi_st_gid = buf->st_gid;
91 nacl_buf->nacl_abi_st_rdev = buf->st_rdev;
92 nacl_buf->nacl_abi_st_size = buf->st_size;
93 nacl_buf->nacl_abi_st_blksize = buf->st_blksize;
94 nacl_buf->nacl_abi_st_blocks = buf->st_blocks;
95 nacl_buf->nacl_abi_st_atime = buf->st_atim.tv_sec;
96 nacl_buf->nacl_abi_st_atimensec = buf->st_atim.tv_nsec;
97 nacl_buf->nacl_abi_st_mtime = buf->st_mtim.tv_sec;
98 nacl_buf->nacl_abi_st_mtimensec = buf->st_mtim.tv_nsec;
99 nacl_buf->nacl_abi_st_ctime = buf->st_ctim.tv_sec;
100 nacl_buf->nacl_abi_st_ctimensec = buf->st_ctim.tv_nsec;
103 void nacl_stat_to_stat(const nacl_irt_stat_t* nacl_buf, struct stat* buf) {
104 memset(buf, 0, sizeof(struct stat));
105 buf->st_dev = nacl_buf->nacl_abi_st_dev;
106 buf->st_ino = nacl_buf->nacl_abi_st_ino;
107 buf->st_mode = nacl_buf->nacl_abi_st_mode;
108 buf->st_nlink = nacl_buf->nacl_abi_st_nlink;
109 buf->st_uid = nacl_buf->nacl_abi_st_uid;
110 buf->st_gid = nacl_buf->nacl_abi_st_gid;
111 buf->st_rdev = nacl_buf->nacl_abi_st_rdev;
112 buf->st_size = nacl_buf->nacl_abi_st_size;
113 buf->st_blksize = nacl_buf->nacl_abi_st_blksize;
114 buf->st_blocks = nacl_buf->nacl_abi_st_blocks;
115 buf->st_atim.tv_sec = nacl_buf->nacl_abi_st_atime;
116 buf->st_atim.tv_nsec = nacl_buf->nacl_abi_st_atimensec;
117 buf->st_mtim.tv_sec = nacl_buf->nacl_abi_st_mtime;
118 buf->st_mtim.tv_nsec = nacl_buf->nacl_abi_st_mtimensec;
119 buf->st_ctim.tv_sec = nacl_buf->nacl_abi_st_ctime;
120 buf->st_ctim.tv_nsec = nacl_buf->nacl_abi_st_ctimensec;
124 * IRT interfaces as declared in irt.h.
126 static NACL_IRT_INTERFACE(nacl_irt_basic) s_irt_basic = {
127 NACL_IRT_BASIC_v0_1,
130 static NACL_IRT_INTERFACE(nacl_irt_fdio) s_irt_fdio = {
131 NACL_IRT_FDIO_v0_1,
134 static NACL_IRT_INTERFACE(nacl_irt_memory) s_irt_memory = {
135 NACL_IRT_MEMORY_v0_3,
138 static NACL_IRT_INTERFACE(nacl_irt_resource_open) s_irt_resource_open = {
139 NACL_IRT_RESOURCE_OPEN_v0_1,
143 * IRT Dev interfaces as declared in irt_dev.h.
145 static NACL_IRT_INTERFACE(nacl_irt_dev_fdio) s_irt_dev_fdio = {
146 NACL_IRT_DEV_FDIO_v0_3,
149 static NACL_IRT_INTERFACE(nacl_irt_dev_filename) s_irt_dev_filename = {
150 NACL_IRT_DEV_FILENAME_v0_3,
153 static bool s_wrapped = false;
156 * Functions for the nacl_irt_dev_fdio interface.
158 static int ext_close(int fd) {
159 ERRNO_RTN(ki_close(fd));
162 static int ext_dup(int fd, int *newfd) {
163 *newfd = ki_dup(fd);
164 ERRNO_RTN(*newfd);
167 static int ext_dup2(int fd, int newfd) {
168 newfd = ki_dup2(fd, newfd);
169 ERRNO_RTN(newfd);
172 static int ext_read(int fd, void *buf, size_t count, size_t *nread) {
173 ssize_t signed_nread = ki_read(fd, buf, count);
174 *nread = (size_t) signed_nread;
175 ERRNO_RTN(signed_nread);
178 static int ext_write(int fd, const void *buf, size_t count, size_t *nwrote) {
179 ssize_t signed_nwrote = ki_write(fd, buf, count);
180 *nwrote = (size_t) signed_nwrote;
181 ERRNO_RTN(signed_nwrote);
184 static int ext_seek(int fd, nacl_irt_off_t offset, int whence,
185 nacl_irt_off_t *new_offset) {
186 *new_offset = ki_lseek(fd, offset, whence);
187 ERRNO_RTN(*new_offset);
190 static int ext_fstat(int fd, nacl_irt_stat_t *nacl_buf) {
191 struct stat buf;
192 if (ki_fstat(fd, &buf)) {
193 return errno;
195 stat_to_nacl_stat(&buf, nacl_buf);
196 return 0;
199 static int ext_getdents(int fd, struct dirent *ents, size_t count,
200 size_t *nread) {
201 int rtn = ki_getdents(fd, ents, count);
202 RTN_ERRNO_IF(rtn < 0);
203 *nread = rtn;
204 return 0;
208 * Functions for the nacl_irt_memory interface.
210 static int ext_mmap(void **addr, size_t len, int prot, int flags, int fd,
211 nacl_irt_off_t off) {
212 if (flags & MAP_ANONYMOUS)
213 return s_irt_memory.interface.mmap(addr, len, prot, flags, fd, off);
215 *addr = ki_mmap(*addr, len, prot, flags, fd, off);
216 RTN_ERRNO_IF(*addr == (void*)-1);
217 return 0;
220 static int ext_munmap(void *addr, size_t length) {
222 * Always let the real munmap run on the address range. It is not an error if
223 * there are no mapped pages in that range.
225 ki_munmap(addr, length);
226 return s_irt_memory.interface.munmap(addr, length);
230 * Extra functions for the nacl_irt_dev_fdio interface.
232 static int ext_fchdir(int fd) {
233 ERRNO_RTN(ki_fchdir(fd));
236 static int ext_fchmod(int fd, mode_t mode) {
237 ERRNO_RTN(ki_fchmod(fd, mode));
240 static int ext_fsync(int fd) {
241 ERRNO_RTN(ki_fsync(fd));
244 static int ext_fdatasync(int fd) {
245 ERRNO_RTN(ki_fdatasync(fd));
248 static int ext_ftruncate(int fd, nacl_irt_off_t length) {
249 ERRNO_RTN(ki_ftruncate(fd, length));
252 static int ext_isatty(int fd, int *result) {
253 *result = ki_isatty(fd);
254 RTN_ERRNO_IF(*result == 0);
255 return 0;
259 * Functions for the nacl_irt_dev_filename interface.
261 static int ext_open(const char *pathname, int oflag, mode_t cmode, int *newfd) {
262 *newfd = ki_open(pathname, oflag, cmode);
263 ERRNO_RTN(*newfd);
266 static int ext_stat(const char *pathname, nacl_irt_stat_t *nacl_buf) {
267 struct stat buf;
268 if (ki_stat(pathname, &buf)) {
269 return errno;
271 stat_to_nacl_stat(&buf, nacl_buf);
272 return 0;
275 static int ext_mkdir(const char *pathname, mode_t mode) {
276 ERRNO_RTN(ki_mkdir(pathname, mode));
279 static int ext_rmdir(const char *pathname) {
280 ERRNO_RTN(ki_rmdir(pathname));
283 static int ext_chdir(const char *pathname) {
284 ERRNO_RTN(ki_chdir(pathname));
287 static int ext_getcwd(char *pathname, size_t len) {
288 char *rtn = ki_getcwd(pathname, len);
289 RTN_ERRNO_IF(NULL == rtn);
290 return 0;
293 static int ext_unlink(const char *pathname) {
294 ERRNO_RTN(ki_unlink(pathname));
297 static int ext_truncate(const char *pathname, nacl_irt_off_t length) {
298 ERRNO_RTN(ki_truncate(pathname, length));
301 static int ext_lstat(const char *pathname, nacl_irt_stat_t *nacl_buf) {
302 struct stat buf;
303 if (ki_lstat(pathname, &buf)) {
304 return errno;
306 stat_to_nacl_stat(&buf, nacl_buf);
307 return 0;
310 static int ext_link(const char *pathname, const char *newpath) {
311 ERRNO_RTN(ki_link(pathname, newpath));
314 static int ext_rename(const char *pathname, const char *newpath) {
315 ERRNO_RTN(ki_rename(pathname, newpath));
318 static int ext_symlink(const char *pathname, const char *newpath) {
319 ERRNO_RTN(ki_symlink(pathname, newpath));
322 static int ext_chmod(const char *pathname, mode_t mode) {
323 ERRNO_RTN(ki_chmod(pathname, mode));
326 static int ext_access(const char *pathname, int amode) {
327 ERRNO_RTN(ki_access(pathname, amode));
330 static int ext_readlink(const char *pathname, char *buf, size_t count,
331 size_t *nread) {
332 int rtn = ki_readlink(pathname, buf, count);
333 RTN_ERRNO_IF(rtn < 0);
334 *nread = rtn;
335 return 0;
338 static int ext_utimes(const char *pathname, const struct timeval *times) {
339 ERRNO_RTN(ki_utimes(pathname, times));
343 * Functions declared inside of kernel_wrap_real.h.
346 int _real_close(int fd) {
347 INIT_INTERFACE_ENOSYS(s_irt_fdio);
348 return s_irt_fdio.interface.close(fd);
351 void _real_exit(int status) {
352 INIT_INTERFACE_ASSERT(s_irt_basic);
353 return s_irt_basic.interface.exit(status);
356 int _real_fstat(int fd, struct stat *buf) {
357 INIT_INTERFACE_ENOSYS(s_irt_fdio);
358 nacl_irt_stat_t nacl_buf;
359 int err = s_irt_fdio.interface.fstat(fd, &nacl_buf);
360 if (err) {
361 errno = err;
362 return -1;
364 nacl_stat_to_stat(&nacl_buf, buf);
365 return 0;
368 int _real_getdents(int fd, void *nacl_buf, size_t nacl_count, size_t *nread) {
369 INIT_INTERFACE_ENOSYS(s_irt_fdio);
370 return s_irt_fdio.interface.getdents(fd, (struct dirent *) nacl_buf,
371 nacl_count, nread);
374 int _real_isatty(int fd, int *result) {
375 INIT_INTERFACE_ENOSYS(s_irt_dev_fdio);
376 return s_irt_dev_fdio.interface.isatty(fd, result);
379 int _real_lseek(int fd, int64_t offset, int whence, int64_t *new_offset) {
380 INIT_INTERFACE_ENOSYS(s_irt_fdio);
381 return s_irt_fdio.interface.seek(fd, offset, whence, new_offset);
384 int _real_mkdir(const char *pathname, mode_t mode) {
385 INIT_INTERFACE_ENOSYS(s_irt_dev_filename);
386 return s_irt_dev_filename.interface.mkdir(pathname, mode);
389 int _real_mmap(void **addr,
390 size_t length,
391 int prot,
392 int flags,
393 int fd,
394 int64_t offset) {
395 INIT_INTERFACE_ENOSYS(s_irt_memory);
396 return s_irt_memory.interface.mmap(addr, length, prot, flags, fd, offset);
399 int _real_munmap(void *addr, size_t length) {
400 INIT_INTERFACE_ENOSYS(s_irt_memory);
401 return s_irt_memory.interface.munmap(addr, length);
404 int _real_open(const char *pathname, int oflag, mode_t mode, int *newfd) {
405 INIT_INTERFACE_ENOSYS(s_irt_dev_filename);
406 return s_irt_dev_filename.interface.open(pathname, oflag, mode, newfd);
409 int _real_open_resource(const char *file, int *fd) {
410 INIT_INTERFACE_ENOSYS(s_irt_resource_open);
411 return s_irt_resource_open.interface.open_resource(file, fd);
414 int _real_read(int fd, void *buf, size_t count, size_t *nread) {
415 INIT_INTERFACE_ENOSYS(s_irt_fdio);
416 return s_irt_fdio.interface.read(fd, buf, count, nread);
419 int _real_rmdir(const char *pathname) {
420 INIT_INTERFACE_ENOSYS(s_irt_dev_filename);
421 return s_irt_dev_filename.interface.rmdir(pathname);
424 int _real_write(int fd, const void *buf, size_t count, size_t *nwrote) {
425 INIT_INTERFACE_ENOSYS(s_irt_fdio);
426 return s_irt_fdio.interface.write(fd, buf, count, nwrote);
429 int _real_getcwd(char *pathname, size_t len) {
430 INIT_INTERFACE_ENOSYS(s_irt_dev_filename);
431 return s_irt_dev_filename.interface.getcwd(pathname, len);
435 * Kernel Wrap init/uninit functions declared in kernel_wrap.h.
437 void kernel_wrap_init() {
438 if (!s_wrapped) {
439 LOG_TRACE("kernel_wrap_init");
442 * Register interfaces as listed in irt.h.
445 /* Register nacl_irt_basic interface. */
446 INIT_INTERFACE_ASSERT(s_irt_basic);
447 struct nacl_irt_basic basic_calls = {
448 ki_exit,
449 s_irt_basic.interface.gettod,
450 s_irt_basic.interface.clock,
451 s_irt_basic.interface.nanosleep,
452 s_irt_basic.interface.sched_yield,
453 s_irt_basic.interface.sysconf,
455 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_basic, basic_calls);
457 /* Register nacl_irt_fdio interface. */
458 INIT_INTERFACE(s_irt_fdio);
459 struct nacl_irt_fdio fdio = {
460 ext_close,
461 ext_dup,
462 ext_dup2,
463 ext_read,
464 ext_write,
465 ext_seek,
466 ext_fstat,
467 ext_getdents,
469 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_fdio, fdio);
471 /* Register nacl_irt_memory interface. */
472 INIT_INTERFACE_ASSERT(s_irt_memory);
473 struct nacl_irt_memory mem = {
474 ext_mmap,
475 ext_munmap,
476 s_irt_memory.interface.mprotect,
478 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_memory, mem);
481 * Register interfaces as listed in irt_dev.h.
484 /* Register nacl_irt_dev_fdio interface. */
485 INIT_INTERFACE(s_irt_dev_fdio);
486 struct nacl_irt_dev_fdio dev_fdio = {
487 ext_close,
488 ext_dup,
489 ext_dup2,
490 ext_read,
491 ext_write,
492 ext_seek,
493 ext_fstat,
494 ext_getdents,
495 ext_fchdir,
496 ext_fchmod,
497 ext_fsync,
498 ext_fdatasync,
499 ext_ftruncate,
500 ext_isatty,
502 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_fdio, dev_fdio);
504 /* Register nacl_irt_dev_filename interface. */
505 INIT_INTERFACE(s_irt_dev_filename);
506 struct nacl_irt_dev_filename dev_filename = {
507 ext_open,
508 ext_stat,
509 ext_mkdir,
510 ext_rmdir,
511 ext_chdir,
512 ext_getcwd,
513 ext_unlink,
514 ext_truncate,
515 ext_lstat,
516 ext_link,
517 ext_rename,
518 ext_symlink,
519 ext_chmod,
520 ext_access,
521 ext_readlink,
522 ext_utimes,
524 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_filename, dev_filename);
526 s_wrapped = true;
530 void kernel_wrap_uninit() {
531 if (s_wrapped) {
532 LOG_TRACE("kernel_wrap_uninit");
534 /* Register original IRT interfaces in irt.h. */
535 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_basic,
536 s_irt_basic.interface);
538 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_fdio,
539 s_irt_fdio.interface);
541 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_memory,
542 s_irt_memory.interface);
545 * Register optional original IRT dev interfaces in irt_dev.h, these
546 * may or may not exist since they are dev interfaces. If they do not
547 * exist go ahead and supply an empty interface as that's what they
548 * were originally before we supplied any extension interfaces.
550 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_fdio,
551 s_irt_dev_fdio.interface);
553 EXT_SUPPLY_INTERFACE_ASSERT(s_irt_dev_filename,
554 s_irt_dev_filename.interface);
556 s_wrapped = false;
560 #endif