Index: ports/glibc-compat/src/openat.c |
diff --git a/ports/glibc-compat/src/openat.c b/ports/glibc-compat/src/openat.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..562053d45832bbc0c5534de3d4f478017c0a8bb0 |
--- /dev/null |
+++ b/ports/glibc-compat/src/openat.c |
@@ -0,0 +1,156 @@ |
+/* |
+ * Copyright 2015 The Native Client Authors. All rights reserved. |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+#include <fcntl.h> |
+#include <sys/stat.h> |
+#include <unistd.h> |
+#include <limits.h> |
+#include <dirent.h> |
+#include <errno.h> |
+#include <stdlib.h> |
+#include <stdio.h> |
+ |
+// xgetcwd is pulled from toybox lib/xwrap.c |
+static char *xgetcwd(void) { |
+ char *buf = (char*)malloc(sizeof(char) * (PATH_MAX+1)); |
+ if (buf == NULL) { |
+ fprintf(stderr, "malloc failed\n"); |
+ exit(1); |
+ } |
+ buf = getcwd(buf, PATH_MAX+1); |
+ if (!buf) { |
+ perror("xgetcwd"); |
+ exit(1); |
+ } |
+ return buf; |
+} |
+ |
+// The following functions are pulled from toybox nacl.patch |
+#define _AT_WRAP_START(A) \ |
+ int fchdir_err = 0; \ |
+ char *save = xgetcwd(); \ |
+ if (!save) { \ |
+ perror("fd_wrapper_"A); \ |
+ exit(1); \ |
+ } \ |
+ if (dirfd != AT_FDCWD) { \ |
+ fchdir_err = fchdir(dirfd); \ |
+ if (fchdir_err == -1) \ |
+ perror("fchdir"); \ |
+ } |
+ |
+#define _AT_WRAP_END(A) \ |
+ if (dirfd != AT_FDCWD) chdir(save); \ |
+ free(save); |
+ |
+int openat(int dirfd, const char *pathname, int flags, ...) { |
+ _AT_WRAP_START("openat") |
+ printf("New dir is: %s\n", xgetcwd()); |
+ int fd = open(pathname, flags); |
+ _AT_WRAP_END("openat") |
+ return fd; |
+} |
+ |
+int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags) { |
+ // We are going to ignore flags here. |
+ //if (flags) perror_exit("fstatat_flags"); |
+ _AT_WRAP_START("fstatat") |
+ int result; |
+ if (flags & AT_SYMLINK_NOFOLLOW) |
+ result = lstat(pathname, buf); |
+ else |
+ result = stat(pathname, buf); |
+ _AT_WRAP_END("fstatat") |
+ return result; |
+} |
+ |
+int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags) { |
+ // We are going to ignore flags here. |
+ //if (flags) perror_exit("fchmodat_flags"); |
+ _AT_WRAP_START("fchmodat") |
+ int result = chmod(pathname, mode); |
+ _AT_WRAP_END("fchmodat") |
+ return result; |
+} |
+ |
+int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) { |
+ _AT_WRAP_START("readlinkat") |
+ int result = readlink(pathname, buf, bufsiz); |
+ _AT_WRAP_END("readlinkat") |
+ return result; |
+} |
+ |
+int unlinkat(int dirfd, const char *pathname, int flags) { |
+ // We are going to ignore flags here. |
+ //if (flags) perror_exit("unlinkat_flags"); |
+ _AT_WRAP_START("unlinkat") |
+ int result; |
+ if(flags & AT_REMOVEDIR) { |
+ result = rmdir(pathname); |
+ } else { |
+ result = unlink(pathname); |
+ } |
+ _AT_WRAP_END("unlinkat") |
+ return result; |
+} |
+ |
+int faccessat(int dirfd, const char *pathname, int mode, int flags) { |
+ //if (flags) perror_exit("faccessat_flags"); |
+ _AT_WRAP_START("faccessat") |
+ int result = access(pathname, mode); |
+ _AT_WRAP_END("faccessat") |
+ return result; |
+} |
+ |
+DIR *fdopendir(int dirfd) { |
+ _AT_WRAP_START("fdopendir") |
+ DIR *dir; |
+ if (fchdir_err) { |
+ perror("fdopendir: "); |
+ } |
+ dir = opendir("."); |
+ _AT_WRAP_END("fdopendir") |
+ return dir; |
+} |
+ |
+int mkdirat(int dirfd, const char *pathname, mode_t mode) { |
+ _AT_WRAP_START("mkdirat") |
+ int result = mkdir(pathname, mode); |
+ _AT_WRAP_END("mkdirat") |
+ return result; |
+} |
+ |
+int mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev) { |
+ fprintf(stderr, "mknod not supported\n"); |
+ return 1; |
+} |
+ |
+int fchownat(int dirfd, const char *pathname, uid_t owner, |
+ gid_t group, int flags) { |
+ _AT_WRAP_START("fchownat") |
+ int result = chown(pathname, owner, group); |
+ _AT_WRAP_END("fchownat") |
+ return result; |
+} |
+ |
+int symlinkat(const char *oldpath, int dirfd, const char *newpath) { |
+ _AT_WRAP_START("symlinkat") |
+ int result = symlink(oldpath, newpath); |
+ _AT_WRAP_END("symlinkat") |
+ return result; |
+} |
+ |
+int linkat(int olddirfd, const char *oldpath, |
+ int newdirfd, const char *newpath, int flags) { |
+ int result; |
+ if ((oldpath[0] == '/') && (newpath[0] == '/')) { |
+ result = link(oldpath, newpath); |
+ } else { |
+ errno = EINVAL; |
+ result = -1; |
+ } |
+ // We do not support double linking. |
+ return result; |
+} |