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// The entire file is wrapped in this #if. We do this so this .cc file can be
6// compiled, even on a non-Windows build.
7#if defined(WIN32)
8
9#include "nacl_io/kernel_wrap.h"
10#include <errno.h>
11#include <fcntl.h>
12#include <stdarg.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/types.h>  // This must be included before <sys/stat.h>.
16#include <sys/stat.h>
17#include "nacl_io/kernel_intercept.h"
18
19#include <windows.h>
20
21namespace {
22
23template <typename SrcStat, typename DstStat>
24void CopyStat(const SrcStat* src, DstStat* dst) {
25  memset(dst, 0, sizeof(DstStat));
26  dst->st_dev = src->st_dev;
27  dst->st_ino = src->st_ino;
28  dst->st_mode = src->st_mode;
29  dst->st_nlink = src->st_nlink;
30  dst->st_uid = src->st_uid;
31  dst->st_gid = src->st_gid;
32  dst->st_rdev = src->st_rdev;
33  dst->st_size = src->st_size;
34  dst->st_atime = src->st_atime;
35  dst->st_mtime = src->st_mtime;
36  dst->st_ctime = src->st_ctime;
37}
38
39}  // namespace
40
41EXTERN_C_BEGIN
42
43// This needs to be included because it is defined in read.c, which we wish to
44// override. Define with dummy values for now... though this seems like it will
45// break ftelli64/fgetpos/fstream.
46char _lookuptrailbytes[256] = {0};
47
48int _access(const char* path, int amode) {
49  return ki_access(path, amode);
50}
51
52int _chdir(const char* path) {
53  return ki_chdir(path);
54}
55
56int _chmod(const char* path, mode_t mode) {
57  return ki_chmod(path, mode);
58}
59
60int _close(int fd) {
61  return ki_close(fd);
62}
63
64int _close_nolock(int fd) {
65  return ki_close(fd);
66}
67
68int _dup(int oldfd) {
69  return ki_dup(oldfd);
70}
71
72int _dup2(int oldfd, int newfd) {
73  return ki_dup2(oldfd, newfd);
74}
75
76int _fstat32(int fd, struct _stat32* buf) {
77  struct stat ki_buf;
78  int res = ki_fstat(fd, &ki_buf);
79  CopyStat(&ki_buf, buf);
80  return res;
81}
82
83int _fstat64(int fd, struct _stat64* buf) {
84  struct stat ki_buf;
85  int res = ki_fstat(fd, &ki_buf);
86  CopyStat(&ki_buf, buf);
87  return res;
88}
89
90int _fstat32i64(int fd, struct _stat32i64* buf) {
91  struct stat ki_buf;
92  int res = ki_fstat(fd, &ki_buf);
93  CopyStat(&ki_buf, buf);
94  return res;
95}
96
97int _fstat64i32(int fd, struct _stat64i32* buf) {
98  struct stat ki_buf;
99  int res = ki_fstat(fd, &ki_buf);
100  CopyStat(&ki_buf, buf);
101  return res;
102}
103
104char* _getcwd(char* buf, int size) {
105  return ki_getcwd(buf, size);
106}
107
108int _isatty(int fd) {
109  return ki_isatty(fd);
110}
111
112off_t _lseek(int fd, off_t offset, int whence) {
113  return ki_lseek(fd, offset, whence);
114}
115
116int _mkdir(const char* path) {
117  return ki_mkdir(path, 0777);
118}
119
120int _open(const char* path, int oflag, ...) {
121#if 0
122  // TODO(binji): ki_open should use the pmode parameter. When it does, this
123  // will be necessary to add in.
124  va_list list;
125  int pmode = 0;
126  if (oflag & _O_CREAT) {
127    va_start(list, oflag);
128    pmode = va_arg(list, int);
129    va_end(list);
130  }
131#endif
132  return ki_open(path, oflag);
133}
134
135int _sopen(const char* path, int oflag, int shflag) {
136  return ki_open(path, oflag);
137}
138
139errno_t _sopen_s(int* pfh, const char* path, int oflag, int shflag, int pmode) {
140  *pfh = ki_open(path, oflag);
141  return (*pfh < 0) ? errno : 0;
142}
143
144int _read(int fd, void* buf, size_t nbyte) {
145  if (!ki_is_initialized())
146    return 0;
147
148  return ki_read(fd, buf, nbyte);
149}
150
151int _read_nolock(int fd, void* buf, size_t nbyte) {
152  if (!ki_is_initialized())
153    return 0;
154
155  return ki_read(fd, buf, nbyte);
156}
157
158int _rmdir(const char* path) {
159  return ki_rmdir(path);
160}
161
162int setenv(const char* name, const char* value, int overwrite) {
163  if (0 == overwrite && NULL != getenv(name)) {
164    return 0;
165  }
166  errno_t result = _putenv_s(name, value);
167  if (result != 0) {
168    errno = result;
169    return -1;
170  } else {
171    return 0;
172  }
173}
174
175int _stat32(const char* path, struct _stat32* buf) {
176  struct stat ki_buf;
177  int res = ki_stat(path, &ki_buf);
178  CopyStat(&ki_buf, buf);
179  return res;
180}
181
182int _stat64(const char* path, struct _stat64* buf) {
183  struct stat ki_buf;
184  int res = ki_stat(path, &ki_buf);
185  CopyStat(&ki_buf, buf);
186  return res;
187}
188
189int _stat64i32(const char* path, struct _stat64i32* buf) {
190  struct stat ki_buf;
191  int res = ki_stat(path, &ki_buf);
192  CopyStat(&ki_buf, buf);
193  return res;
194}
195
196int _stat32i64(const char* path, struct _stat32i64* buf) {
197  struct stat ki_buf;
198  int res = ki_stat(path, &ki_buf);
199  CopyStat(&ki_buf, buf);
200  return res;
201}
202
203int _unlink(const char* path) {
204  return ki_unlink(path);
205}
206
207int _utime(const char* filename, const struct utimbuf* times) {
208  return ki_utime(filename, times);
209}
210
211int _write(int fd, const void* buf, size_t nbyte) {
212  if (!ki_is_initialized())
213    return 0;
214
215  return ki_write(fd, buf, nbyte);
216}
217
218
219// "real" functions, i.e. the unwrapped original functions. On Windows we don't
220// wrap, so the real functions aren't accessible. In most cases, we just fail.
221
222int _real_close(int fd) {
223  return ENOSYS;
224}
225
226int _real_fstat(int fd, struct stat *buf) {
227  return 0;
228}
229
230int _real_getdents(int fd, void* nacl_buf, size_t nacl_count, size_t *nread) {
231  return ENOSYS;
232}
233
234int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset) {
235  return ENOSYS;
236}
237
238int _real_mkdir(const char* pathname, mode_t mode) {
239  return ENOSYS;
240}
241
242int _real_mmap(void** addr, size_t length, int prot, int flags, int fd,
243               off_t offset) {
244  return ENOSYS;
245}
246
247int _real_munmap(void* addr, size_t length) {
248  return ENOSYS;
249}
250
251int _real_open(const char* pathname, int oflag, mode_t cmode, int* newfd) {
252  return ENOSYS;
253}
254
255int _real_open_resource(const char* file, int* fd) {
256  return ENOSYS;
257}
258
259int _real_read(int fd, void *buf, size_t count, size_t *nread) {
260  *nread = count;
261  return 0;
262}
263
264int _real_rmdir(const char* pathname) {
265  return ENOSYS;
266}
267
268int _real_write(int fd, const void *buf, size_t count, size_t *nwrote) {
269  *nwrote = count;
270  return 0;
271}
272
273#define USECS_FROM_WIN_TO_TO_UNIX_EPOCH 11644473600000LL
274uint64_t usec_since_epoch() {
275  FILETIME ft;
276  ULARGE_INTEGER ularge;
277  GetSystemTimeAsFileTime(&ft);
278
279  ularge.LowPart = ft.dwLowDateTime;
280  ularge.HighPart = ft.dwHighDateTime;
281
282  // Truncate to usec resolution.
283  return ularge.QuadPart / 10;
284}
285
286// Do nothing for Windows, we replace the library at link time.
287void kernel_wrap_init() {
288}
289
290void kernel_wrap_uninit() {
291}
292
293EXTERN_C_END
294
295#endif   // defined(WIN32)
296
297