Index: native_client_sdk/src/libraries/nacl_io/kernel_wrap_dummy.cc |
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_dummy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_dummy.cc |
index c4d0df8607039cbc471947fc99f975357a8372d9..a4c2a68c065ea4e9e7d2e54d81fdf7a24f3267a6 100644 |
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_dummy.cc |
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_dummy.cc |
@@ -8,6 +8,20 @@ |
#include <errno.h> |
+#ifdef __linux__ |
+#include <dirent.h> |
+#include <stddef.h> |
+#include <string.h> |
+#include <sys/syscall.h> |
+#include <unistd.h> |
+struct linux_dirent { |
+ unsigned long d_ino; /* Inode number */ |
+ unsigned long d_off; /* Offset to next linux_dirent */ |
+ unsigned short d_reclen; /* Length of this linux_dirent */ |
+ char d_name[]; /* Filename (null-terminated) */ |
+}; |
+#endif |
+ |
#include "nacl_io/kernel_wrap.h" |
#include "nacl_io/kernel_wrap_real.h" |
@@ -20,11 +34,41 @@ int _real_close(int fd) { |
} |
int _real_fstat(int fd, struct stat* buf) { |
+ return fstat(fd, buf); |
+} |
+ |
+int _real_getdents(int fd, void* in_buf, size_t in_count, size_t* nread) { |
+#ifdef __linux__ |
+ int in_offset = 0; |
+ // "buf" contains linux_dirent(s); "in_buf" contains dirent(s). |
+ // dirents(s) are smaller than linux_dirent(s), so in_count bytes buffer |
+ // is enough |
binji
2015/01/07 19:14:59
Will this do the right thing if you request one di
Sam Clegg
2015/01/08 12:59:07
in_count is normally much bigger than the size of
|
+ char* buf = (char*)alloca(in_count); |
+ int offset = 0; |
+ int count; |
+ |
+ count = syscall(SYS_getdents, fd, buf, in_count); |
+ if (count < 0) |
+ return errno; |
+ |
+ while (offset < count) { |
+ struct linux_dirent* d = (struct linux_dirent*)(buf + offset); |
+ struct dirent* nacl_d = (struct dirent*)((char*)in_buf + in_offset); |
binji
2015/01/07 19:14:59
consistency between in_ and nacl_ prefixes?
Sam Clegg
2015/01/08 12:59:07
Done.
|
+ nacl_d->d_ino = d->d_ino; |
+ nacl_d->d_off = d->d_off; |
+ nacl_d->d_reclen = d->d_reclen; |
+ size_t d_name_len = d->d_reclen - offsetof(linux_dirent, d_name); |
+ memcpy(nacl_d->d_name, d->d_name, d_name_len); |
+ |
+ offset += d->d_reclen; |
+ in_offset += nacl_d->d_reclen; |
+ } |
+ |
+ *nread = in_offset; |
return 0; |
-} |
- |
-int _real_getdents(int fd, void* nacl_buf, size_t nacl_count, size_t* nread) { |
+#else |
return ENOSYS; |
+#endif |
} |
int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset) { |
@@ -49,7 +93,12 @@ int _real_munmap(void* addr, size_t length) { |
} |
int _real_open(const char* pathname, int oflag, mode_t mode, int* newfd) { |
- return ENOSYS; |
+ int fd = open(pathname, oflag, mode); |
+ if (fd < 0) |
+ return errno; |
+ |
+ *newfd = fd; |
+ return 0; |
} |
int _real_open_resource(const char* file, int* fd) { |
@@ -57,7 +106,11 @@ int _real_open_resource(const char* file, int* fd) { |
} |
int _real_read(int fd, void* buf, size_t count, size_t* nread) { |
- *nread = count; |
+ int rtn = read(fd, buf, count); |
+ if (rtn < 0) |
+ return errno; |
+ |
+ *nread = rtn; |
return 0; |
} |
@@ -68,7 +121,7 @@ int _real_rmdir(const char* pathname) { |
int _real_write(int fd, const void* buf, size_t count, size_t* nwrote) { |
int rtn = write(fd, buf, count); |
if (rtn < 0) |
- return -1; |
+ return errno; |
*nwrote = rtn; |
return 0; |