Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / libraries / nacl_io / kernel_wrap_newlib.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 __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-newlib build.
9 #if defined(__native_client__) && !defined(__GLIBC__) && !defined(__BIONIC__)
10
11 #include "nacl_io/kernel_wrap.h"
12
13 #include <dirent.h>
14 #include <errno.h>
15 #include <irt.h>
16 #include <irt_dev.h>
17 #include <sys/mman.h>
18 #include <sys/stat.h>
19 #include <sys/time.h>
20
21 #include "nacl_io/kernel_intercept.h"
22 #include "nacl_io/kernel_wrap_real.h"
23 #include "nacl_io/log.h"
24
25 EXTERN_C_BEGIN
26
27 // Macro to get the REAL function pointer
28 #define REAL(name) __nacl_irt_##name##_real
29
30 // Macro to get the WRAP function
31 #define WRAP(name) __nacl_irt_##name##_wrap
32
33 // Declare REAL function pointer.
34 #define DECLARE_REAL_PTR(group, name) \
35   typeof(__libnacl_irt_##group.name) REAL(name);
36
37 // Assign the REAL function pointer.
38 #define ASSIGN_REAL_PTR(group, name) REAL(name) = __libnacl_irt_##group.name;
39
40 // Switch IRT's pointer to the REAL pointer
41 #define USE_REAL(group, name) \
42   __libnacl_irt_##group.name = (typeof(REAL(name)))REAL(name);
43
44 // Switch the IRT's pointer to the WRAP function
45 #define USE_WRAP(group, name) \
46   __libnacl_irt_##group.name = (typeof(REAL(name)))WRAP(name);
47
48 extern void __libnacl_irt_dev_filename_init(void);
49 extern void __libnacl_irt_dev_fdio_init(void);
50
51 extern struct nacl_irt_basic __libnacl_irt_basic;
52 extern struct nacl_irt_fdio __libnacl_irt_fdio;
53 extern struct nacl_irt_dev_fdio __libnacl_irt_dev_fdio;
54 extern struct nacl_irt_dev_filename __libnacl_irt_dev_filename;
55 extern struct nacl_irt_memory __libnacl_irt_memory;
56
57 // Create function pointers to the REAL implementation
58 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \
59   OP(basic, exit);                       \
60   OP(fdio, close);                       \
61   OP(fdio, dup);                         \
62   OP(fdio, dup2);                        \
63   OP(fdio, read);                        \
64   OP(fdio, write);                       \
65   OP(fdio, seek);                        \
66   OP(fdio, fstat);                       \
67   OP(fdio, getdents);                    \
68   OP(dev_fdio, fchdir);                  \
69   OP(dev_fdio, fchmod);                  \
70   OP(dev_fdio, fsync);                   \
71   OP(dev_fdio, fdatasync);               \
72   OP(dev_fdio, ftruncate);               \
73   OP(dev_fdio, isatty);                  \
74   OP(dev_filename, open);                \
75   OP(dev_filename, stat);                \
76   OP(dev_filename, mkdir);               \
77   OP(dev_filename, rmdir);               \
78   OP(dev_filename, chdir);               \
79   OP(dev_filename, getcwd);              \
80   OP(dev_filename, unlink);              \
81   OP(dev_filename, truncate);            \
82   OP(dev_filename, lstat);               \
83   OP(dev_filename, link);                \
84   OP(dev_filename, rename);              \
85   OP(dev_filename, symlink);             \
86   OP(dev_filename, chmod);               \
87   OP(dev_filename, access);              \
88   OP(dev_filename, readlink);            \
89   OP(dev_filename, utimes);              \
90   OP(memory, mmap);                      \
91   OP(memory, munmap);
92
93 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR);
94
95 int WRAP(close)(int fd) {
96   ERRNO_RTN(ki_close(fd));
97 }
98
99 int WRAP(dup)(int fd, int* newfd) {
100   *newfd = ki_dup(fd);
101   ERRNO_RTN(*newfd);
102 }
103
104 int WRAP(dup2)(int fd, int newfd) {
105   newfd = ki_dup2(fd, newfd);
106   ERRNO_RTN(newfd);
107 }
108
109 void WRAP(exit)(int status) {
110   ki_exit(status);
111 }
112
113 int WRAP(read)(int fd, void* buf, size_t count, size_t* nread) {
114   ssize_t signed_nread = ki_read(fd, buf, count);
115   *nread = static_cast<size_t>(signed_nread);
116   ERRNO_RTN(signed_nread);
117 }
118
119 int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) {
120   ssize_t signed_nwrote = ki_write(fd, buf, count);
121   *nwrote = static_cast<size_t>(signed_nwrote);
122   ERRNO_RTN(signed_nwrote);
123 }
124
125 int WRAP(seek)(int fd, off_t offset, int whence, off_t* new_offset) {
126   *new_offset = ki_lseek(fd, offset, whence);
127   ERRNO_RTN(*new_offset);
128 }
129
130 int WRAP(fstat)(int fd, struct stat* buf) {
131   ERRNO_RTN(ki_fstat(fd, buf));
132 }
133
134 int WRAP(getdents)(int fd, dirent* buf, size_t count, size_t* nread) {
135   int rtn = ki_getdents(fd, buf, count);
136   RTN_ERRNO_IF(rtn < 0);
137   *nread = rtn;
138   return 0;
139 }
140
141 int WRAP(fchdir)(int fd) {
142   ERRNO_RTN(ki_fchdir(fd));
143 }
144
145 int WRAP(fchmod)(int fd, mode_t mode) {
146   ERRNO_RTN(ki_fchmod(fd, mode));
147 }
148
149 int WRAP(fsync)(int fd) {
150   ERRNO_RTN(ki_fsync(fd));
151 }
152
153 int WRAP(fdatasync)(int fd) {
154   ERRNO_RTN(ki_fdatasync(fd));
155 }
156
157 int WRAP(ftruncate)(int fd, off_t length) {
158   ERRNO_RTN(ki_ftruncate(fd, length));
159 }
160
161 int WRAP(isatty)(int fd, int* result) {
162   *result = ki_isatty(fd);
163   RTN_ERRNO_IF(*result == 0);
164   return 0;
165 }
166
167 int WRAP(mmap)(void** addr,
168                size_t length,
169                int prot,
170                int flags,
171                int fd,
172                off_t offset) {
173   if (flags & MAP_ANONYMOUS)
174     return REAL(mmap)(addr, length, prot, flags, fd, offset);
175
176   *addr = ki_mmap(*addr, length, prot, flags, fd, offset);
177   RTN_ERRNO_IF(*addr == (void*)-1);
178   return 0;
179 }
180
181 int WRAP(munmap)(void* addr, size_t length) {
182   // Always let the real munmap run on the address range. It is not an error if
183   // there are no mapped pages in that range.
184   ki_munmap(addr, length);
185   return REAL(munmap)(addr, length);
186 }
187
188 int WRAP(open)(const char* pathname, int oflag, mode_t cmode, int* newfd) {
189   *newfd = ki_open(pathname, oflag);
190   ERRNO_RTN(*newfd);
191 }
192
193 int WRAP(stat)(const char* pathname, struct stat* buf) {
194   ERRNO_RTN(ki_stat(pathname, buf));
195 }
196
197 int WRAP(mkdir)(const char* pathname, mode_t mode) {
198   ERRNO_RTN(ki_mkdir(pathname, mode));
199 }
200
201 int WRAP(rmdir)(const char* pathname) {
202   ERRNO_RTN(ki_rmdir(pathname));
203 }
204
205 int WRAP(chdir)(const char* pathname) {
206   ERRNO_RTN(ki_chdir(pathname));
207 }
208
209 int WRAP(getcwd)(char* pathname, size_t len) {
210   char* rtn = ki_getcwd(pathname, len);
211   RTN_ERRNO_IF(NULL == rtn);
212   return 0;
213 }
214
215 int WRAP(unlink)(const char* pathname) {
216   ERRNO_RTN(ki_unlink(pathname));
217 }
218
219 int WRAP(truncate)(const char* pathname, off_t length) {
220   ERRNO_RTN(ki_truncate(pathname, length));
221 }
222
223 int WRAP(lstat)(const char* pathname, struct stat* buf) {
224   ERRNO_RTN(ki_lstat(pathname, buf));
225 }
226
227 int WRAP(link)(const char* pathname, const char* newpath) {
228   ERRNO_RTN(ki_link(pathname, newpath));
229 }
230
231 int WRAP(rename)(const char* pathname, const char* newpath) {
232   ERRNO_RTN(ki_rename(pathname, newpath));
233 }
234
235 int WRAP(symlink)(const char* pathname, const char* newpath) {
236   ERRNO_RTN(ki_symlink(pathname, newpath));
237 }
238
239 int WRAP(chmod)(const char* pathname, mode_t mode) {
240   ERRNO_RTN(ki_chmod(pathname, mode));
241 }
242
243 int WRAP(access)(const char* pathname, int amode) {
244   ERRNO_RTN(ki_access(pathname, amode));
245 }
246
247 int WRAP(readlink)(const char* pathname,
248                    char* buf,
249                    size_t count,
250                    size_t* nread) {
251   int rtn = ki_readlink(pathname, buf, count);
252   RTN_ERRNO_IF(rtn < 0);
253   *nread = rtn;
254   return 0;
255 }
256
257 int WRAP(utimes)(const char* pathname, const struct timeval times[2]) {
258   ERRNO_RTN(ki_utimes(pathname, times));
259 }
260
261 static void assign_real_pointers() {
262   static bool assigned = false;
263   if (!assigned) {
264     __libnacl_irt_dev_filename_init();
265     __libnacl_irt_dev_fdio_init();
266     EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
267     assigned = true;
268   }
269 }
270
271 #define CHECK_REAL(func)    \
272   if (!REAL(func))          \
273     assign_real_pointers();
274
275 // "real" functions, i.e. the unwrapped original functions.
276
277 int _real_close(int fd) {
278   CHECK_REAL(close);
279   return REAL(close)(fd);
280 }
281
282 void _real_exit(int status) {
283   CHECK_REAL(exit);
284   REAL(exit)(status);
285 }
286
287 int _real_fstat(int fd, struct stat* buf) {
288   CHECK_REAL(fstat);
289   return REAL(fstat)(fd, buf);
290 }
291
292 int _real_isatty(int fd, int* result) {
293   CHECK_REAL(isatty);
294   // The real isatty function can be NULL (for example if we are running
295   // withing chrome).
296   if (REAL(isatty) == NULL) {
297     *result = 0;
298     return ENOTTY;
299   }
300   return REAL(isatty)(fd, result);
301 }
302
303 int _real_getdents(int fd, void* nacl_buf, size_t nacl_count, size_t* nread) {
304   CHECK_REAL(getdents);
305   return REAL(getdents)(fd, static_cast<dirent*>(nacl_buf), nacl_count, nread);
306 }
307
308 int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset) {
309   CHECK_REAL(seek);
310   return REAL(seek)(fd, offset, whence, new_offset);
311 }
312
313 int _real_mkdir(const char* pathname, mode_t mode) {
314   CHECK_REAL(mkdir);
315   return REAL(mkdir)(pathname, mode);
316 }
317
318 int _real_mmap(void** addr,
319                size_t length,
320                int prot,
321                int flags,
322                int fd,
323                off_t offset) {
324   CHECK_REAL(mmap);
325   return REAL(mmap)(addr, length, prot, flags, fd, offset);
326 }
327
328 int _real_munmap(void* addr, size_t length) {
329   CHECK_REAL(munmap);
330   return REAL(munmap)(addr, length);
331 }
332
333 int _real_open(const char* pathname, int oflag, mode_t cmode, int* newfd) {
334   CHECK_REAL(open);
335   return REAL(open)(pathname, oflag, cmode, newfd);
336 }
337
338 int _real_open_resource(const char* file, int* fd) {
339   return ENOSYS;
340 }
341
342 int _real_read(int fd, void* buf, size_t count, size_t* nread) {
343   CHECK_REAL(read);
344   return REAL(read)(fd, buf, count, nread);
345 }
346
347 int _real_rmdir(const char* pathname) {
348   CHECK_REAL(rmdir);
349   return REAL(rmdir)(pathname);
350 }
351
352 int _real_write(int fd, const void* buf, size_t count, size_t* nwrote) {
353   CHECK_REAL(write);
354   return REAL(write)(fd, buf, count, nwrote);
355 }
356
357 static bool s_wrapped = false;
358
359 void kernel_wrap_init() {
360   if (!s_wrapped) {
361     LOG_TRACE("kernel_wrap_init");
362     assign_real_pointers();
363     EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
364     s_wrapped = true;
365   }
366 }
367
368 void kernel_wrap_uninit() {
369   if (s_wrapped) {
370     LOG_TRACE("kernel_wrap_uninit");
371     EXPAND_SYMBOL_LIST_OPERATION(USE_REAL)
372     s_wrapped = false;
373   }
374 }
375
376 EXTERN_C_END
377
378 #endif  // defined(__native_client__) && !defined(__GLIBC__) ...