Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / libraries / nacl_io / kernel_wrap_bionic.cc
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.
4
5 #include <sys/types.h>  // Include something that will define __BIONIC__.
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-bionic build.
9
10 #if defined(__native_client__) && defined(__BIONIC__)
11 #include <alloca.h>
12 #include <assert.h>
13 #include <dirent.h>
14 #include <errno.h>
15 #include <irt_syscalls.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <sys/time.h>
19
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"
24
25 namespace {
26
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;
42 }
43
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;
59 }
60
61 }  // namespace
62
63 // From native_client/src/trusted/service_runtime/include/sys/dirent.h
64
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;
69 #endif
70
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;
75 #endif
76
77 /* We need a way to define the maximum size of a name. */
78 #ifndef MAXNAMLEN
79 # ifdef NAME_MAX
80 #  define MAXNAMLEN NAME_MAX
81 # else
82 #  define MAXNAMLEN 255
83 # endif
84 #endif
85
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];
91 };
92
93 static const int d_name_shift = offsetof (dirent, d_name) -
94   offsetof (struct nacl_abi_dirent, nacl_abi_d_name);
95
96 EXTERN_C_BEGIN
97
98 // Macro to get the REAL function pointer
99 #define REAL(name) __nacl_irt_##name##_real
100
101 // Macro to get the WRAP function
102 #define WRAP(name) __nacl_irt_##name##_wrap
103
104 // Declare REAL function pointer.
105 #define DECLARE_REAL_PTR(name) \
106   typeof(__nacl_irt_##name) REAL(name);
107
108 // Assign the REAL function pointer.
109 #define ASSIGN_REAL_PTR(name) \
110   REAL(name) = __nacl_irt_##name;
111
112 // Switch IRT's pointer to the REAL pointer
113 #define USE_REAL(name) \
114   __nacl_irt_##name = (typeof(__nacl_irt_##name)) REAL(name)
115
116 // Switch IRT's pointer to the WRAP function
117 #define USE_WRAP(name) \
118   __nacl_irt_##name = (typeof(__nacl_irt_##name)) WRAP(name)
119
120
121 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \
122   OP(chdir); \
123   OP(close); \
124   OP(dup); \
125   OP(dup2);  \
126   OP(exit); \
127   OP(fchdir); \
128   OP(fchmod); \
129   OP(fdatasync); \
130   OP(fstat); \
131   OP(fsync); \
132   OP(getcwd); \
133   OP(getdents); \
134   OP(isatty); \
135   OP(lstat); \
136   OP(mkdir); \
137   OP(mmap); \
138   OP(munmap); \
139   OP(open); \
140   OP(open_resource); \
141   OP(poll); \
142   OP(read); \
143   OP(readlink); \
144   OP(rmdir); \
145   OP(seek); \
146   OP(stat); \
147   OP(truncate); \
148   OP(write); \
149
150
151 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR);
152
153 int WRAP(chdir)(const char* pathname) {
154   return (ki_chdir(pathname)) ? errno : 0;
155 }
156
157 int WRAP(close)(int fd) {
158   return (ki_close(fd) < 0) ? errno : 0;
159 }
160
161 int WRAP(dup)(int fd, int* newfd) NOTHROW {
162   *newfd = ki_dup(fd);
163   return (*newfd < 0) ? errno : 0;
164 }
165
166 int WRAP(dup2)(int fd, int newfd) NOTHROW {
167   return (ki_dup2(fd, newfd) < 0) ? errno : 0;
168 }
169
170 void WRAP(exit)(int status) {
171   ki_exit(status);
172 }
173
174 int WRAP(fchdir)(int fd) NOTHROW {
175   return (ki_fchdir(fd)) ? errno : 0;
176 }
177
178 int WRAP(fchmod)(int fd, mode_t mode) NOTHROW {
179   return (ki_fchmod(fd, mode)) ? errno : 0;
180 }
181
182 int WRAP(fdatasync)(int fd) NOTHROW {
183   return (ki_fdatasync(fd)) ? errno : 0;
184 }
185
186 int WRAP(fstat)(int fd, struct nacl_abi_stat *nacl_buf) {
187   struct stat buf;
188   memset(&buf, 0, sizeof(struct stat));
189   int res = ki_fstat(fd, &buf);
190   if (res < 0)
191     return errno;
192   stat_to_nacl_stat(&buf, nacl_buf);
193   return 0;
194 }
195
196 int WRAP(fsync)(int fd) NOTHROW {
197   return (ki_fsync(fd)) ? errno : 0;
198 }
199
200 int WRAP(getcwd)(char* buf, size_t size) {
201   if (ki_getcwd(buf, size) == NULL)
202     return errno;
203   return 0;
204 }
205
206 int WRAP(getdents)(int fd, dirent* nacl_buf, size_t nacl_count, size_t *nread) {
207   int nacl_offset = 0;
208   // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
209   // nacl_abi_dirent(s) are smaller than dirent(s), so nacl_count bytes buffer
210   // is enough
211   char* buf = (char*)alloca(nacl_count);
212   int offset = 0;
213   int count;
214
215   count = ki_getdents(fd, buf, nacl_count);
216   if (count < 0)
217     return errno;
218
219   while (offset < count) {
220     dirent* d = (dirent*)(buf + offset);
221     nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)((char*)nacl_buf + nacl_offset);
222     nacl_d->nacl_abi_d_ino = d->d_ino;
223     nacl_d->nacl_abi_d_off = d->d_off;
224     nacl_d->nacl_abi_d_reclen = d->d_reclen - d_name_shift;
225     size_t d_name_len = d->d_reclen - offsetof(dirent, d_name);
226     memcpy(nacl_d->nacl_abi_d_name, d->d_name, d_name_len);
227
228     offset += d->d_reclen;
229     nacl_offset += nacl_d->nacl_abi_d_reclen;
230   }
231
232   *nread = nacl_offset;
233   return 0;
234 }
235
236 int WRAP(isatty)(int fd, int* result) {
237   *result = ki_isatty(fd);
238   if (*result == 1)
239     return errno;
240   return 0;
241 }
242
243 int WRAP(lstat)(const char *path, struct nacl_abi_stat* nacl_buf) {
244   struct stat buf;
245   memset(&buf, 0, sizeof(struct stat));
246   int res = ki_lstat(path, &buf);
247   if (res < 0)
248     return errno;
249   stat_to_nacl_stat(&buf, nacl_buf);
250   return 0;
251 }
252
253 int WRAP(mkdir)(const char* pathname, mode_t mode) {
254   return (ki_mkdir(pathname, mode)) ? errno : 0;
255 }
256
257 int WRAP(mmap)(void** addr, size_t length, int prot, int flags, int fd,
258                int64_t offset) {
259   if (flags & MAP_ANONYMOUS)
260     return REAL(mmap)(addr, length, prot, flags, fd, offset);
261
262   *addr = ki_mmap(*addr, length, prot, flags, fd, offset);
263   return *addr == (void*)-1 ? errno : 0;
264 }
265
266 int WRAP(munmap)(void* addr, size_t length) {
267   // Always let the real munmap run on the address range. It is not an error if
268   // there are no mapped pages in that range.
269   ki_munmap(addr, length);
270   return REAL(munmap)(addr, length);
271 }
272
273 int WRAP(open)(const char* pathname, int oflag, mode_t cmode, int* newfd) {
274   *newfd = ki_open(pathname, oflag);
275   return (*newfd < 0) ? errno : 0;
276 }
277
278 int WRAP(open_resource)(const char* file, int* fd) {
279   *fd = ki_open_resource(file);
280   return (*fd < 0) ? errno : 0;
281 }
282
283 int WRAP(poll)(struct pollfd *fds, nfds_t nfds, int timeout, int* count) {
284   *count = ki_poll(fds, nfds, timeout);
285   return (*count < 0) ? errno : 0;
286
287 }
288
289 int WRAP(read)(int fd, void *buf, size_t count, size_t *nread) {
290   ssize_t signed_nread = ki_read(fd, buf, count);
291   *nread = static_cast<size_t>(signed_nread);
292   return (signed_nread < 0) ? errno : 0;
293 }
294
295 int WRAP(readlink)(const char* path, char* buf, size_t count, size_t* nread) {
296   ssize_t signed_nread = ki_readlink(path, buf, count);
297   *nread = static_cast<size_t>(signed_nread);
298   return (signed_nread < 0) ? errno : 0;
299 }
300
301 int WRAP(rmdir)(const char* pathname) {
302   return (ki_rmdir(pathname) < 0) ? errno : 0;
303 }
304
305 int WRAP(seek)(int fd, off64_t offset, int whence, int64_t* new_offset) {
306   *new_offset = ki_lseek(fd, offset, whence);
307   return (*new_offset < 0) ? errno : 0;
308 }
309
310 int WRAP(select)(int nfds, fd_set* readfds, fd_set* writefds,
311                  fd_set* exceptfds, struct timeval* timeout, int* count) {
312   *count = ki_select(nfds, readfds, writefds, exceptfds, timeout);
313   return (*count < 0) ? errno : 0;
314 }
315
316 int WRAP(stat)(const char *pathname, struct nacl_abi_stat *nacl_buf) {
317   struct stat buf;
318   memset(&buf, 0, sizeof(struct stat));
319   int res = ki_stat(pathname, &buf);
320   if (res < 0)
321     return errno;
322   stat_to_nacl_stat(&buf, nacl_buf);
323   return 0;
324 }
325
326 int WRAP(truncate)(const char *name, int64_t len) {
327   return (ki_truncate(name, len)) ? errno : 0;
328 }
329
330 int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) {
331   ssize_t signed_nwrote = ki_write(fd, buf, count);
332   *nwrote = static_cast<size_t>(signed_nwrote);
333   return (signed_nwrote < 0) ? errno : 0;
334 }
335
336 static void assign_real_pointers() {
337   static bool assigned = false;
338   if (!assigned) {
339     EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
340     assigned = true;
341   }
342 }
343
344 #define CHECK_REAL(func) \
345   if (!REAL(func)) \
346     assign_real_pointers();
347
348 // "real" functions, i.e. the unwrapped original functions.
349
350 int _real_close(int fd) {
351   CHECK_REAL(close);
352   return REAL(close)(fd);
353 }
354
355 void _real_exit(int status) {
356   REAL(exit)(status);
357 }
358
359 int _real_fchdir(int fd) {
360   CHECK_REAL(fchdir);
361   return REAL(fchdir)(fd);
362 }
363
364 int _real_fchmod(int fd, mode_t mode) {
365   CHECK_REAL(fchmod);
366   return REAL(fchmod)(fd, mode);
367 }
368
369 int _real_fdatasync(int fd) {
370   CHECK_REAL(fdatasync);
371   return REAL(fdatasync)(fd);
372 }
373
374 int _real_fstat(int fd, struct stat* buf) {
375   struct nacl_abi_stat st;
376   CHECK_REAL(fstat);
377
378   int err = REAL(fstat)(fd, (struct stat*) &st);
379   if (err) {
380     errno = err;
381     return -1;
382   }
383
384   nacl_stat_to_stat(&st, buf);
385   return 0;
386 }
387
388 int _real_fsync(int fd) {
389   CHECK_REAL(fsync);
390   return REAL(fsync)(fd);
391 }
392
393 int _real_getdents(int fd, void* buf, size_t count, size_t* nread) {
394   // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s).
395   // See WRAP(getdents) above.
396   char* nacl_buf = (char*)alloca(count);
397   size_t offset = 0;
398   size_t nacl_offset = 0;
399   size_t nacl_nread;
400   CHECK_REAL(getdents);
401   int err = REAL(getdents)(fd, (dirent*)nacl_buf, count, &nacl_nread);
402   if (err)
403     return err;
404
405   while (nacl_offset < nacl_nread) {
406     dirent* d = (dirent*)((char*)buf + offset);
407     nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)(nacl_buf + nacl_offset);
408     d->d_ino = nacl_d->nacl_abi_d_ino;
409     d->d_off = nacl_d->nacl_abi_d_off;
410     d->d_reclen = nacl_d->nacl_abi_d_reclen + d_name_shift;
411     size_t d_name_len = nacl_d->nacl_abi_d_reclen -
412         offsetof(nacl_abi_dirent, nacl_abi_d_name);
413     memcpy(d->d_name, nacl_d->nacl_abi_d_name, d_name_len);
414
415     offset += d->d_reclen;
416     offset += nacl_d->nacl_abi_d_reclen;
417   }
418
419   *nread = offset;
420   return 0;
421 }
422
423 int _real_isatty(int fd, int* result) {
424   *result = isatty(fd);
425   return *result ? 0 : -1;
426 }
427
428 int _real_lseek(int fd, int64_t offset, int whence, int64_t* new_offset) {
429   CHECK_REAL(seek);
430   nacl_abi_off_t nacl_new_offs;
431   int ret = REAL(seek)(fd, offset, whence, &nacl_new_offs);
432   *new_offset = static_cast<off_t>(nacl_new_offs);
433   return ret;
434 }
435
436 int _real_lstat(const char* path, struct stat* buf) {
437   struct nacl_abi_stat st;
438   CHECK_REAL(fstat);
439
440   int err = REAL(lstat)(path, (struct stat*) &st);
441   if (err) {
442     errno = err;
443     return -1;
444   }
445
446   nacl_stat_to_stat(&st, buf);
447   return 0;
448 }
449
450
451 int _real_mkdir(const char* pathname, mode_t mode) {
452   CHECK_REAL(mkdir);
453   return REAL(mkdir)(pathname, mode);
454 }
455
456 int _real_mmap(void** addr, size_t length, int prot, int flags, int fd,
457                int64_t offset) {
458   CHECK_REAL(mmap);
459   return REAL(mmap)(addr, length, prot, flags, fd, offset);
460 }
461
462 int _real_munmap(void* addr, size_t length) {
463   CHECK_REAL(munmap);
464   return REAL(munmap)(addr, length);
465 }
466
467 int _real_open(const char* pathname, int oflag, mode_t cmode, int* newfd) {
468   CHECK_REAL(open);
469   return REAL(open)(pathname, oflag, cmode, newfd);
470 }
471
472 int _real_open_resource(const char* file, int* fd) {
473   CHECK_REAL(open_resource);
474   return REAL(open_resource)(file, fd);
475 }
476
477 int _real_read(int fd, void *buf, size_t count, size_t *nread) {
478   CHECK_REAL(read);
479   return REAL(read)(fd, buf, count, nread);
480 }
481
482 int _real_readlink(const char *path, char* buf, size_t count, size_t* nread) {
483   CHECK_REAL(readlink);
484   return REAL(readlink)(path, buf, count, nread);
485 }
486
487 int _real_rmdir(const char* pathname) {
488   CHECK_REAL(rmdir);
489   return REAL(rmdir)(pathname);
490 }
491
492 int _real_truncate(const char* pathname, int64_t len) {
493   CHECK_REAL(truncate);
494   return REAL(truncate)(pathname, len);
495 }
496
497 int _real_write(int fd, const void *buf, size_t count, size_t *nwrote) {
498   CHECK_REAL(write);
499   return REAL(write)(fd, buf, count, nwrote);
500 }
501
502 static bool s_wrapped = false;
503 void kernel_wrap_init() {
504   if (!s_wrapped) {
505     assign_real_pointers();
506     EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
507     s_wrapped = true;
508   }
509 }
510
511 void kernel_wrap_uninit() {
512   if (s_wrapped) {
513     EXPAND_SYMBOL_LIST_OPERATION(USE_REAL)
514     s_wrapped = false;
515   }
516 }
517
518 EXTERN_C_END
519
520 #endif  // defined(__native_client__) && defined(__GLIBC__)