aboutsummaryrefslogtreecommitdiffstats
path: root/ports/unix
diff options
context:
space:
mode:
Diffstat (limited to 'ports/unix')
-rw-r--r--ports/unix/guts/COPYRIGHT17
-rw-r--r--ports/unix/guts/access.c31
-rw-r--r--ports/unix/guts/acct.c14
-rw-r--r--ports/unix/guts/chdir.c24
-rw-r--r--ports/unix/guts/chmod.c14
-rw-r--r--ports/unix/guts/chown.c14
-rw-r--r--ports/unix/guts/chroot.c19
-rw-r--r--ports/unix/guts/close.c17
-rw-r--r--ports/unix/guts/creat.c14
-rw-r--r--ports/unix/guts/dup.c19
-rw-r--r--ports/unix/guts/dup2.c22
-rw-r--r--ports/unix/guts/fchdir.c18
-rw-r--r--ports/unix/guts/fchmod.c31
-rw-r--r--ports/unix/guts/fchmodat.c71
-rw-r--r--ports/unix/guts/fchown.c55
-rw-r--r--ports/unix/guts/fchownat.c67
-rw-r--r--ports/unix/guts/fclose.c20
-rw-r--r--ports/unix/guts/fopen.c35
-rw-r--r--ports/unix/guts/freopen.c35
-rw-r--r--ports/unix/guts/fts_open.c46
-rw-r--r--ports/unix/guts/ftw.c14
-rw-r--r--ports/unix/guts/getcwd.c67
-rw-r--r--ports/unix/guts/getwd.c21
-rw-r--r--ports/unix/guts/glob.c36
-rw-r--r--ports/unix/guts/lchown.c13
-rw-r--r--ports/unix/guts/link.c36
-rw-r--r--ports/unix/guts/lutimes.c14
-rw-r--r--ports/unix/guts/mkdir.c14
-rw-r--r--ports/unix/guts/mkdirat.c37
-rw-r--r--ports/unix/guts/mkdtemp.c46
-rw-r--r--ports/unix/guts/mkfifo.c14
-rw-r--r--ports/unix/guts/mkfifoat.c14
-rw-r--r--ports/unix/guts/mknod.c13
-rw-r--r--ports/unix/guts/mknodat.c66
-rw-r--r--ports/unix/guts/mkstemp.c47
-rw-r--r--ports/unix/guts/mktemp.c36
-rw-r--r--ports/unix/guts/nftw.c14
-rw-r--r--ports/unix/guts/opendir.c14
-rw-r--r--ports/unix/guts/pathconf.c14
-rw-r--r--ports/unix/guts/readlink.c14
-rw-r--r--ports/unix/guts/readlinkat.c25
-rw-r--r--ports/unix/guts/realpath.c30
-rw-r--r--ports/unix/guts/remove.c22
-rw-r--r--ports/unix/guts/rename.c96
-rw-r--r--ports/unix/guts/renameat.c15
-rw-r--r--ports/unix/guts/rmdir.c36
-rw-r--r--ports/unix/guts/symlink.c14
-rw-r--r--ports/unix/guts/symlinkat.c52
-rw-r--r--ports/unix/guts/tempnam.c18
-rw-r--r--ports/unix/guts/tmpnam.c18
-rw-r--r--ports/unix/guts/truncate.c14
-rw-r--r--ports/unix/guts/unlink.c14
-rw-r--r--ports/unix/guts/unlinkat.c61
-rw-r--r--ports/unix/guts/utime.c13
-rw-r--r--ports/unix/guts/utimes.c13
-rw-r--r--ports/unix/wrapfuncs.in56
56 files changed, 1624 insertions, 0 deletions
diff --git a/ports/unix/guts/COPYRIGHT b/ports/unix/guts/COPYRIGHT
new file mode 100644
index 0000000..c96e1b1
--- /dev/null
+++ b/ports/unix/guts/COPYRIGHT
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the Lesser GNU General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Lesser GNU General Public License for more details.
+ *
+ * You should have received a copy of the Lesser GNU General Public License
+ * version 2.1 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
diff --git a/ports/unix/guts/access.c b/ports/unix/guts/access.c
new file mode 100644
index 0000000..5a92957
--- /dev/null
+++ b/ports/unix/guts/access.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_access(const char *path, int mode) {
+ * int rc = -1;
+ */
+ struct stat buf;
+
+ /* note: no attempt to handle the case where user isn't
+ * root.
+ */
+ rc = real_stat(path, &buf);
+ if (rc == -1)
+ return rc;
+
+ if (mode & X_OK) {
+ if (buf.st_mode & 0111) {
+ return 0;
+ } else {
+ errno = EPERM;
+ return -1;
+ }
+ } else {
+ return 0;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/acct.c b/ports/unix/guts/acct.c
new file mode 100644
index 0000000..b8dca5d
--- /dev/null
+++ b/ports/unix/guts/acct.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_acct(const char *path) {
+ * int rc = -1;
+ */
+
+ rc = real_acct(path);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/chdir.c b/ports/unix/guts/chdir.c
new file mode 100644
index 0000000..59a262f
--- /dev/null
+++ b/ports/unix/guts/chdir.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_chdir(const char *path) {
+ * int rc = -1;
+ */
+ pseudo_debug(2, "chdir: '%s'\n",
+ path ? path : "<nil>");
+
+ if (!path) {
+ errno = EFAULT;
+ return -1;
+ }
+ rc = real_chdir(path);
+
+ if (rc != -1) {
+ pseudo_client_op(OP_CHDIR, 0, -1, -1, path, 0);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/chmod.c b/ports/unix/guts/chmod.c
new file mode 100644
index 0000000..a157335
--- /dev/null
+++ b/ports/unix/guts/chmod.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_chmod(const char *path, mode_t mode) {
+ * int rc = -1;
+ */
+
+ rc = wrap_fchmodat(AT_FDCWD, path, mode, 0);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/chown.c b/ports/unix/guts/chown.c
new file mode 100644
index 0000000..4fcbdda
--- /dev/null
+++ b/ports/unix/guts/chown.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_chown(const char *path, uid_t owner, gid_t group) {
+ * int rc = -1;
+ */
+
+ rc = wrap_fchownat(AT_FDCWD, path, owner, group, 0);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/chroot.c b/ports/unix/guts/chroot.c
new file mode 100644
index 0000000..c5b6f2f
--- /dev/null
+++ b/ports/unix/guts/chroot.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_chroot(const char *path) {
+ * int rc = -1;
+ */
+ pseudo_debug(2, "chroot: %s\n", path);
+ if (!pseudo_client_op(OP_CHROOT, 0, -1, -1, path, 0)) {
+ pseudo_debug(1, "chroot failed: %s\n", strerror(errno));
+ rc = -1;
+ } else {
+ rc = 0;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/close.c b/ports/unix/guts/close.c
new file mode 100644
index 0000000..09c73e6
--- /dev/null
+++ b/ports/unix/guts/close.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_close(int fd) {
+ * int rc = -1;
+ */
+ /* this cleans up an internal table, and shouldn't even
+ * make it to the server.
+ */
+ pseudo_client_op(OP_CLOSE, 0, fd, -1, 0, 0);
+ rc = real_close(fd);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/creat.c b/ports/unix/guts/creat.c
new file mode 100644
index 0000000..8593cd4
--- /dev/null
+++ b/ports/unix/guts/creat.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_creat(const char *path, mode_t mode) {
+ * int rc = -1;
+ */
+
+ rc = wrap_open(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/dup.c b/ports/unix/guts/dup.c
new file mode 100644
index 0000000..13612b1
--- /dev/null
+++ b/ports/unix/guts/dup.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_dup(int fd) {
+ * int rc = -1;
+ */
+ int save_errno;
+
+ rc = real_dup(fd);
+ save_errno = errno;
+ pseudo_debug(2, "dup: %d->%d\n", fd, rc);
+ pseudo_client_op(OP_DUP, 0, fd, rc, 0, 0);
+
+ errno = save_errno;
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/dup2.c b/ports/unix/guts/dup2.c
new file mode 100644
index 0000000..04666d1
--- /dev/null
+++ b/ports/unix/guts/dup2.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_dup2(int oldfd, int newfd) {
+ * int rc = -1;
+ */
+ int save_errno;
+
+ /* close existing one first - this also causes the socket to the
+ * server to get moved around if someone tries to overwrite it. */
+ pseudo_debug(2, "dup2: %d->%d\n", oldfd, newfd);
+ pseudo_client_op(OP_CLOSE, 0, newfd, -1, 0, 0);
+ rc = real_dup2(oldfd, newfd);
+ save_errno = errno;
+ pseudo_client_op(OP_DUP, 0, oldfd, newfd, 0, 0);
+ errno = save_errno;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/fchdir.c b/ports/unix/guts/fchdir.c
new file mode 100644
index 0000000..ba77ebf
--- /dev/null
+++ b/ports/unix/guts/fchdir.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_fchdir(int dirfd) {
+ * int rc = -1;
+ */
+
+ rc = real_fchdir(dirfd);
+
+ if (rc != -1) {
+ pseudo_client_op(OP_CHDIR, 0, -1, dirfd, 0, 0);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/fchmod.c b/ports/unix/guts/fchmod.c
new file mode 100644
index 0000000..40f62ba
--- /dev/null
+++ b/ports/unix/guts/fchmod.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_fchmod(int fd, mode_t mode) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ struct stat buf;
+ int save_errno = errno;
+
+ if (real_fstat(fd, &buf) == -1) {
+ /* can't stat it, can't chmod it */
+ return -1;
+ }
+ buf.st_mode = (buf.st_mode & ~07777) | (mode & 07777);
+ msg = pseudo_client_op_plain(OP_FCHMOD, 0, fd, -1, 0, &buf);
+ real_fchmod(fd, PSEUDO_FS_MODE(mode));
+ if (msg && msg->result != RESULT_SUCCEED) {
+ errno = EPERM;
+ rc = -1;
+ } else {
+ /* just pretend we worked */
+ errno = save_errno;
+ rc = 0;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/fchmodat.c b/ports/unix/guts/fchmodat.c
new file mode 100644
index 0000000..531345d
--- /dev/null
+++ b/ports/unix/guts/fchmodat.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_fchmodat(int dirfd, const char *path, mode_t mode, int flags) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ struct stat buf;
+ int save_errno;
+
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+ if (flags & AT_SYMLINK_NOFOLLOW) {
+ rc = real_lstat(path, &buf);
+ } else {
+ rc = real_stat(path, &buf);
+ }
+#else
+ rc = real___fxstatat(_STAT_VER, dirfd, path, &buf, flags);
+#endif
+ if (rc == -1) {
+ return rc;
+ }
+ if (S_ISLNK(buf.st_mode)) {
+ /* we don't really support chmod of a symlink */
+ errno = ENOSYS;
+ return -1;
+ }
+ save_errno = errno;
+
+ /* purely for debugging purposes: check whether file
+ * is already in database.
+ */
+ msg = pseudo_client_op_plain(OP_STAT, 0, -1, -1, path, &buf);
+ if (!msg || msg->result != RESULT_SUCCEED) {
+ pseudo_debug(2, "chmodat to 0%o on %d/%s, ino %llu, new file.\n",
+ mode, dirfd, path, (unsigned long long) buf.st_ino);
+
+ }
+
+ /* user bits added so "root" can always access files. */
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ /* note: if path was a symlink, and AT_NOFOLLOW_SYMLINKS was
+ * specified, we already bailed previously. */
+ real_chmod(path, PSEUDO_FS_MODE(mode));
+#else
+ real_fchmodat(dirfd, path, PSEUDO_FS_MODE(mode), flags);
+#endif
+ /* we ignore a failure from underlying fchmod, because pseudo
+ * may believe you are permitted to change modes that the filesystem
+ * doesn't.
+ */
+
+ buf.st_mode = (buf.st_mode & ~07777) | (mode & 07777);
+ msg = pseudo_client_op_plain(OP_CHMOD, 0, -1, dirfd, path, &buf);
+ if (msg && msg->result != RESULT_SUCCEED) {
+ errno = EPERM;
+ rc = -1;
+ } else {
+ /* if server is down, just pretend we worked */
+ rc = 0;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/fchown.c b/ports/unix/guts/fchown.c
new file mode 100644
index 0000000..c36a869
--- /dev/null
+++ b/ports/unix/guts/fchown.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_fchown(int fd, uid_t owner, gid_t group) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ struct stat buf;
+ int save_errno;
+
+ if (real_fstat(fd, &buf) == -1) {
+ save_errno = errno;
+ pseudo_debug(2, "fchown failing because fstat failed: %s\n",
+ strerror(errno));
+ errno = save_errno;
+ return -1;
+ }
+ if (owner == (uid_t) -1 || group == (gid_t) -1) {
+ msg = pseudo_client_op_plain(OP_STAT, 0, fd, -1, NULL, &buf);
+ /* copy in any existing values... */
+ if (msg) {
+ if (msg->result == RESULT_SUCCEED) {
+ pseudo_stat_msg_plain(&buf, msg);
+ } else {
+ pseudo_debug(2, "fchown fd %d, ino %llu, unknown file.\n",
+ fd, (unsigned long long) buf.st_ino);
+ }
+ } else {
+ pseudo_diag("stat within chown of fd %d [%llu] failed.\n",
+ fd, (unsigned long long) buf.st_ino);
+ }
+ }
+ /* now override with arguments */
+ if (owner != (uid_t) -1) {
+ buf.st_uid = owner;
+ }
+ if (group != (gid_t) -1) {
+ buf.st_gid = group;
+ }
+ pseudo_debug(2, "fchown, fd %d: %d:%d -> %d:%d\n",
+ fd, owner, group, buf.st_uid, buf.st_gid);
+ msg = pseudo_client_op_plain(OP_FCHOWN, 0, fd, -1, 0, &buf);
+ if (msg && msg->result != RESULT_SUCCEED) {
+ errno = EPERM;
+ rc = -1;
+ } else {
+ /* just pretend we worked */
+ rc = 0;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/fchownat.c b/ports/unix/guts/fchownat.c
new file mode 100644
index 0000000..9585fb0
--- /dev/null
+++ b/ports/unix/guts/fchownat.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ struct stat buf;
+ int save_errno;
+ int doing_link = 0;
+
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+ if (flags & AT_SYMLINK_NOFOLLOW) {
+ rc = real_lstat(path, &buf);
+ } else {
+ rc = real_stat(path, &buf);
+ }
+#else
+ rc = real___fxstatat(_STAT_VER, dirfd, path, &buf, flags);
+#endif
+ if (rc == -1) {
+ return rc;
+ }
+ /* pseudo won't track the ownership, here */
+ if (S_ISLNK(buf.st_mode)) {
+ doing_link = 1;
+ }
+ save_errno = errno;
+
+ if (owner == (uid_t) -1 || group == (gid_t) -1) {
+ msg = pseudo_client_op_plain(OP_STAT, 0, -1, -1, path, &buf);
+ /* copy in any existing values... */
+ if (msg) {
+ if (msg->result == RESULT_SUCCEED) {
+ pseudo_stat_msg_plain(&buf, msg);
+ } else {
+ pseudo_debug(2, "chownat to %d:%d on %d/%s, ino %llu, new file.\n",
+ owner, group, dirfd, path,
+ (unsigned long long) buf.st_ino);
+ }
+ }
+ }
+ /* now override with arguments */
+ if (owner != (uid_t) -1) {
+ buf.st_uid = owner;
+ }
+ if (group != (gid_t) -1) {
+ buf.st_gid = group;
+ }
+ msg = pseudo_client_op_plain(OP_CHOWN, 0, -1, dirfd, path, &buf);
+ if (msg && msg->result != RESULT_SUCCEED) {
+ errno = EPERM;
+ rc = -1;
+ } else {
+ /* just pretend we worked */
+ rc = 0;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/fclose.c b/ports/unix/guts/fclose.c
new file mode 100644
index 0000000..4469f5b
--- /dev/null
+++ b/ports/unix/guts/fclose.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_fclose(FILE *fp) {
+ * int rc = -1;
+ */
+
+ if (!fp) {
+ errno = EFAULT;
+ return -1;
+ }
+ int fd = fileno(fp);
+ pseudo_client_op(OP_CLOSE, 0, fd, -1, 0, 0);
+ rc = real_fclose(fp);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/fopen.c b/ports/unix/guts/fopen.c
new file mode 100644
index 0000000..9dd6c33
--- /dev/null
+++ b/ports/unix/guts/fopen.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static FILE *
+ * wrap_fopen(const char *path, const char *mode) {
+ * FILE * rc = 0;
+ */
+ struct stat buf;
+ int save_errno;
+ int existed = (real_stat(path, &buf) != -1);
+
+ rc = real_fopen(path, mode);
+ save_errno = errno;
+
+ if (rc) {
+ int fd = fileno(rc);
+
+ pseudo_debug(2, "fopen '%s': fd %d <FILE %p>\n", path, fd, (void *) rc);
+ if (real_fstat(fd, &buf) != -1) {
+ if (!existed) {
+ pseudo_client_op_plain(OP_CREAT, 0, -1, -1, path, &buf);
+ }
+ pseudo_client_op_plain(OP_OPEN, pseudo_access_fopen(mode), fd, -1, path, &buf);
+ } else {
+ pseudo_debug(1, "fopen (fd %d) succeeded, but fstat failed (%s).\n",
+ fd, strerror(errno));
+ pseudo_client_op_plain(OP_OPEN, pseudo_access_fopen(mode), fd, -1, path, 0);
+ }
+ errno = save_errno;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/freopen.c b/ports/unix/guts/freopen.c
new file mode 100644
index 0000000..b5a7bfc
--- /dev/null
+++ b/ports/unix/guts/freopen.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static FILE *
+ * wrap_freopen(const char *path, const char *mode, FILE *stream) {
+ * FILE * rc = NULL;
+ */
+ struct stat buf;
+ int save_errno;
+ int existed = (real_stat(path, &buf) != -1);
+
+ rc = real_freopen(path, mode, stream);
+ save_errno = errno;
+
+ if (rc) {
+ int fd = fileno(rc);
+
+ pseudo_debug(2, "freopen '%s': fd %d\n", path, fd);
+ if (real_fstat(fd, &buf) != -1) {
+ if (!existed) {
+ pseudo_client_op_plain(OP_CREAT, 0, -1, -1, path, &buf);
+ }
+ pseudo_client_op_plain(OP_OPEN, pseudo_access_fopen(mode), fd, -1, path, &buf);
+ } else {
+ pseudo_debug(1, "fopen (fd %d) succeeded, but stat failed (%s).\n",
+ fd, strerror(errno));
+ pseudo_client_op_plain(OP_OPEN, pseudo_access_fopen(mode), fd, -1, path, 0);
+ }
+ errno = save_errno;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/fts_open.c b/ports/unix/guts/fts_open.c
new file mode 100644
index 0000000..8b3ce19
--- /dev/null
+++ b/ports/unix/guts/fts_open.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static FTS *
+ * wrap_fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)) {
+ * FTS * rc = NULL;
+ */
+ char **rpath_argv;
+ int args = 0;
+ int errored = 0;
+ int i;
+
+ if (!path_argv) {
+ errno = EFAULT;
+ return NULL;
+ }
+ /* count args */
+ for (i = 0; path_argv[i]; ++i) {
+ ++args;
+ }
+ rpath_argv = malloc((args + 1) * sizeof(*rpath_argv));
+ if (!rpath_argv) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ for (i = 0; i < args; ++i) {
+ rpath_argv[i] = PSEUDO_ROOT_PATH(AT_FDCWD, path_argv[i], AT_SYMLINK_NOFOLLOW);
+ if (!rpath_argv[i])
+ errored = 1;
+ }
+
+ if (errored) {
+ errno = ENOMEM;
+ rc = NULL;
+ } else {
+ rc = real_fts_open(path_argv, options, compar);
+ }
+ for (i = 0; i < args; ++i)
+ free(rpath_argv[i]);
+ free(rpath_argv);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/ftw.c b/ports/unix/guts/ftw.c
new file mode 100644
index 0000000..0861194
--- /dev/null
+++ b/ports/unix/guts/ftw.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int nopenfd) {
+ * int rc = -1;
+ */
+
+ rc = real_ftw(path, fn, nopenfd);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/getcwd.c b/ports/unix/guts/getcwd.c
new file mode 100644
index 0000000..b3f552c
--- /dev/null
+++ b/ports/unix/guts/getcwd.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static char *
+ * wrap_getcwd(char *buf, size_t size) {
+ * char * rc = NULL;
+ */
+ pseudo_debug(3, "wrap_getcwd: %p, %lu\n",
+ (void *) buf, (unsigned long) size);
+ if (!pseudo_cwd) {
+ pseudo_diag("Asked for CWD, but don't have it!\n");
+ errno = EACCES;
+ return NULL;
+ }
+ /* emulate Linux semantics in case of non-Linux systems. */
+ if (!buf) {
+ /* if we don't have a cwd, something's very wrong... */
+ if (!size) {
+ size = pseudo_cwd_len + 1;
+ if (pseudo_chroot_len && size >= pseudo_chroot_len &&
+ !memcmp(pseudo_cwd, pseudo_chroot, pseudo_chroot_len)) {
+ size -= pseudo_chroot_len;
+ /* if cwd is precisely the same as chroot, we
+ * actually want a /, not an empty string
+ */
+ if (size < 2)
+ size = 2;
+ }
+ }
+ if (size) {
+ buf = malloc(size);
+ } else {
+ pseudo_diag("can't figure out CWD: length %ld + 1 - %ld => %ld\n",
+ (unsigned long) pseudo_cwd_len,
+ (unsigned long) pseudo_chroot_len,
+ (unsigned long) size);
+ }
+ if (!buf) {
+ pseudo_diag("couldn't allocate requested CWD buffer - need %ld byes\n",
+ (unsigned long) size);
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+ if (pseudo_cwd_len - (pseudo_cwd_rel - pseudo_cwd) >= size) {
+ pseudo_debug(1, "only %ld bytes available, need %ld (%ld + 1 - %ld)\n",
+ (unsigned long) size,
+ (unsigned long) pseudo_cwd_len + 1 - pseudo_chroot_len,
+ (unsigned long) pseudo_cwd_len,
+ (unsigned long) pseudo_chroot_len);
+ errno = ERANGE;
+ return NULL;
+ }
+ rc = buf;
+ pseudo_debug(3, "getcwd: copying %d (%d + 1 - %d) characters from <%s>.\n",
+ (int) ((pseudo_cwd_len + 1) - pseudo_chroot_len),
+ (int) pseudo_cwd_len, (int) pseudo_chroot_len,
+ pseudo_cwd_rel);
+ memcpy(buf, pseudo_cwd_rel, (pseudo_cwd_len + 1) - (pseudo_cwd_rel - pseudo_cwd));
+ if (!*buf) {
+ strcpy(buf, "/");
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/getwd.c b/ports/unix/guts/getwd.c
new file mode 100644
index 0000000..836301e
--- /dev/null
+++ b/ports/unix/guts/getwd.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static char *
+ * wrap_getwd(char *buf) {
+ * char * rc = NULL;
+ */
+
+ pseudo_debug(3, "getwd (getcwd)\n");
+ rc = wrap_getcwd(buf, pseudo_path_max());
+ /* because it would violate everything we have ever known about
+ * UNIX for these functions to have the same errno semantics,
+ * that's why.
+ */
+ if (rc == NULL && errno == ERANGE )
+ errno = ENAMETOOLONG;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/glob.c b/ports/unix/guts/glob.c
new file mode 100644
index 0000000..0012179
--- /dev/null
+++ b/ports/unix/guts/glob.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) {
+ * int rc = -1;
+ */
+ char *rpattern = NULL;
+ int alloced = 0;
+
+ /* note: no canonicalization */
+ if (pattern && (*pattern == '/') && pseudo_chroot_len) {
+ size_t len = strlen(pattern) + pseudo_chroot_len + 2;
+ rpattern = malloc(len);
+ if (!rpattern) {
+ errno = ENOMEM;
+ return GLOB_NOSPACE;
+ }
+ snprintf(rpattern, len, "%s/%s", pseudo_chroot, pattern);
+ alloced = 1;
+ }
+
+ rc = real_glob(alloced ? rpattern : pattern, flags, errfunc, pglob);
+
+ free(rpattern);
+
+ if (rc == 0) {
+ unsigned int i;
+ for (i = 0; i < pglob->gl_pathc; ++i) {
+ pseudo_dechroot(pglob->gl_pathv[i], (size_t) -1);
+ }
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/lchown.c b/ports/unix/guts/lchown.c
new file mode 100644
index 0000000..60727d0
--- /dev/null
+++ b/ports/unix/guts/lchown.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2008,2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int lchown(const char *path, uid_t owner, gid_t group)
+ * int rc = -1;
+ */
+
+ rc = wrap_chown(path, owner, group);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/link.c b/ports/unix/guts/link.c
new file mode 100644
index 0000000..81316e2
--- /dev/null
+++ b/ports/unix/guts/link.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_link(const char *oldpath, const char *newpath) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ struct stat buf;
+
+ rc = real_link(oldpath, newpath);
+ if (rc == 0) {
+ /* link(2) will not overwrite; if it succeeded, we know
+ * that there was no previous file with this name, so we
+ * shove it into the database.
+ */
+ /* On linux, link(2) links to symlinks, not to the
+ * files they link to. This is contraPOSIX, but
+ * it's apparently useful.
+ */
+ real_lstat(oldpath, &buf);
+ /* a link should copy the existing database entry, if
+ * there is one. OP_LINK is also used to insert unseen
+ * files, though, so it can't be implicit.
+ */
+ msg = pseudo_client_op_plain(OP_STAT, 0, -1, -1, oldpath, &buf);
+ if (msg) {
+ pseudo_stat_msg_plain(&buf, msg);
+ }
+ pseudo_client_op_plain(OP_LINK, 0, -1, -1, newpath, &buf);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/lutimes.c b/ports/unix/guts/lutimes.c
new file mode 100644
index 0000000..cdadbbd
--- /dev/null
+++ b/ports/unix/guts/lutimes.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_lutimes(const char *path, const struct timeval *tv) {
+ * int rc = -1;
+ */
+
+ rc = real_lutimes(path, tv);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mkdir.c b/ports/unix/guts/mkdir.c
new file mode 100644
index 0000000..9f116e2
--- /dev/null
+++ b/ports/unix/guts/mkdir.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_mkdir(const char *path, mode_t mode) {
+ * int rc = -1;
+ */
+
+ rc = wrap_mkdirat(AT_FDCWD, path, mode);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mkdirat.c b/ports/unix/guts/mkdirat.c
new file mode 100644
index 0000000..a3d3ca7
--- /dev/null
+++ b/ports/unix/guts/mkdirat.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_mkdirat(int dirfd, const char *path, mode_t mode) {
+ * int rc = -1;
+ */
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+ rc = real_mkdir(path, PSEUDO_FS_MODE(mode));
+#else
+ rc = real_mkdirat(dirfd, path, PSEUDO_FS_MODE(mode));
+#endif
+ if (rc != -1) {
+ struct stat buf;
+ int stat_rc;
+
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ stat_rc = real_lstat(path, &buf);
+#else
+ stat_rc = real___fxstatat(_STAT_VER, dirfd, path, &buf, AT_SYMLINK_NOFOLLOW);
+#endif
+ if (stat_rc != -1) {
+ pseudo_client_op_plain(OP_MKDIR, 0, -1, dirfd, path, &buf);
+ } else {
+ pseudo_debug(1, "mkdir of %s succeeded, but stat failed: %s\n",
+ path, strerror(errno));
+ }
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mkdtemp.c b/ports/unix/guts/mkdtemp.c
new file mode 100644
index 0000000..92d4da7
--- /dev/null
+++ b/ports/unix/guts/mkdtemp.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static char *
+ * wrap_mkdtemp(char *template) {
+ * char * rc = NULL;
+ */
+ struct stat buf;
+ int save_errno;
+ size_t len;
+ char *tmp_template;
+
+ if (!template) {
+ errno = EFAULT;
+ return NULL;
+ }
+
+ len = strlen(template);
+ tmp_template = PSEUDO_ROOT_PATH(AT_FDCWD, template, AT_SYMLINK_NOFOLLOW);
+
+ if (!tmp_template) {
+ errno = ENOENT;
+ return NULL;
+ }
+
+ rc = real_mkdtemp(tmp_template);
+
+ if (rc != NULL) {
+ save_errno = errno;
+
+ if (real_stat(rc, &buf) != -1) {
+ pseudo_client_op_plain(OP_CREAT, 0, -1, -1, tmp_template, &buf);
+ } else {
+ pseudo_debug(1, "mkdtemp (path %s) succeeded, but fstat failed (%s).\n",
+ rc, strerror(errno));
+ }
+ errno = save_errno;
+ }
+ /* mkdtemp only changes the XXXXXX at the end. */
+ memcpy(template + len - 6, tmp_template + strlen(tmp_template) - 6, 6);
+ rc = template;
+ free(tmp_template);
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mkfifo.c b/ports/unix/guts/mkfifo.c
new file mode 100644
index 0000000..32f79fb
--- /dev/null
+++ b/ports/unix/guts/mkfifo.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_mkfifo(const char *path, mode_t mode) {
+ * int rc = -1;
+ */
+
+ rc = wrap_mkfifoat(AT_FDCWD, path, mode);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mkfifoat.c b/ports/unix/guts/mkfifoat.c
new file mode 100644
index 0000000..3497f37
--- /dev/null
+++ b/ports/unix/guts/mkfifoat.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_mkfifoat(int dirfd, const char *path, mode_t mode) {
+ * int rc = -1;
+ */
+
+ rc = wrap_mknodat(dirfd, path, (mode & 07777) | S_IFIFO, (dev_t) 0);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mknod.c b/ports/unix/guts/mknod.c
new file mode 100644
index 0000000..25c2962
--- /dev/null
+++ b/ports/unix/guts/mknod.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int mknod(const char *path, mode_t mode, dev_t dev)
+ * int rc = -1;
+ */
+
+ rc = real_mknod(path, mode, dev);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mknodat.c b/ports/unix/guts/mknodat.c
new file mode 100644
index 0000000..22fe5ce
--- /dev/null
+++ b/ports/unix/guts/mknodat.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev)
+ * int rc = -1;
+ */
+
+ pseudo_msg_t *msg;
+ struct stat buf;
+
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+ rc = real_stat(path, &buf);
+#else
+ rc = real___fxstatat(_STAT_VER, dirfd, path, &buf, AT_SYMLINK_NOFOLLOW);
+#endif
+ if (rc != -1) {
+ /* if we can stat the file, you can't mknod it */
+ errno = EEXIST;
+ return -1;
+ }
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ rc = real_open(path, O_CREAT | O_WRONLY | O_EXCL, PSEUDO_FS_MODE(mode));
+#else
+ rc = real_openat(dirfd, path, O_CREAT | O_WRONLY | O_EXCL,
+ PSEUDO_FS_MODE(mode));
+#endif
+ if (rc == -1) {
+ return -1;
+ }
+ real_fstat(rc, &buf);
+ /* mknod does not really open the file. We don't have
+ * to use wrap_close because we've never exposed this file
+ * descriptor to the client code.
+ */
+ real_close(rc);
+
+ /* mask in the mode type bits again */
+ buf.st_mode = (PSEUDO_DB_MODE(buf.st_mode, mode) & 07777) |
+ (mode & ~07777);
+ buf.st_rdev = dev;
+ msg = pseudo_client_op_plain(OP_MKNOD, 0, -1, dirfd, path, &buf);
+ if (msg && msg->result != RESULT_SUCCEED) {
+ errno = EPERM;
+ rc = -1;
+ } else {
+ /* just pretend we worked */
+ rc = 0;
+ }
+ if (rc == -1) {
+ int save_errno = errno;
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ real_unlink(path);
+#else
+ real_unlinkat(dirfd, path, AT_SYMLINK_NOFOLLOW);
+#endif
+ errno = save_errno;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mkstemp.c b/ports/unix/guts/mkstemp.c
new file mode 100644
index 0000000..46c0be1
--- /dev/null
+++ b/ports/unix/guts/mkstemp.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_mkstemp(char *template) {
+ * int rc = -1;
+ */
+ struct stat buf;
+ int save_errno;
+ size_t len;
+ char *tmp_template;
+
+ if (!template) {
+ errno = EFAULT;
+ return 0;
+ }
+
+ len = strlen(template);
+ tmp_template = PSEUDO_ROOT_PATH(AT_FDCWD, template, AT_SYMLINK_NOFOLLOW);
+
+ if (!tmp_template) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ rc = real_mkstemp(tmp_template);
+
+ if (rc != -1) {
+ save_errno = errno;
+
+ if (real_fstat(rc, &buf) != -1) {
+ pseudo_client_op_plain(OP_CREAT, 0, -1, -1, tmp_template, &buf);
+ pseudo_client_op_plain(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, &buf);
+ } else {
+ pseudo_debug(1, "mkstemp (fd %d) succeeded, but fstat failed (%s).\n",
+ rc, strerror(errno));
+ pseudo_client_op_plain(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, 0);
+ }
+ errno = save_errno;
+ }
+ /* mkstemp only changes the XXXXXX at the end. */
+ memcpy(template + len - 6, tmp_template + strlen(tmp_template) - 6, 6);
+ free(tmp_template);
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mktemp.c b/ports/unix/guts/mktemp.c
new file mode 100644
index 0000000..7cf594a
--- /dev/null
+++ b/ports/unix/guts/mktemp.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static char *
+ * wrap_mktemp(char *template) {
+ * char * rc = NULL;
+ */
+ size_t len;
+ char *tmp_template;
+
+ if (!template) {
+ errno = EFAULT;
+ return NULL;
+ }
+
+ len = strlen(template);
+ tmp_template = PSEUDO_ROOT_PATH(AT_FDCWD, template, AT_SYMLINK_NOFOLLOW);
+
+ if (!tmp_template) {
+ errno = ENOENT;
+ return NULL;
+ }
+
+ rc = real_mktemp(tmp_template);
+
+ /* mktemp only changes the XXXXXX at the end, and never created
+ * a file -- note the race condition implied here.
+ */
+ memcpy(template + len - 6, tmp_template + strlen(tmp_template) - 6, 6);
+ rc = template;
+ free(tmp_template);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/nftw.c b/ports/unix/guts/nftw.c
new file mode 100644
index 0000000..73daec8
--- /dev/null
+++ b/ports/unix/guts/nftw.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int nopenfd, int flag) {
+ * int rc = -1;
+ */
+
+ rc = real_nftw(path, fn, nopenfd, flag);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/opendir.c b/ports/unix/guts/opendir.c
new file mode 100644
index 0000000..8eaa71f
--- /dev/null
+++ b/ports/unix/guts/opendir.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static DIR *
+ * wrap_opendir(const char *path) {
+ * DIR * rc = NULL;
+ */
+
+ rc = real_opendir(path);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/pathconf.c b/ports/unix/guts/pathconf.c
new file mode 100644
index 0000000..c6caa34
--- /dev/null
+++ b/ports/unix/guts/pathconf.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static long
+ * wrap_pathconf(const char *path, int name) {
+ * long rc = -1;
+ */
+
+ rc = real_pathconf(path, name);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/readlink.c b/ports/unix/guts/readlink.c
new file mode 100644
index 0000000..18d9dc7
--- /dev/null
+++ b/ports/unix/guts/readlink.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static ssize_t
+ * wrap_readlink(const char *path, char *buf, size_t bufsiz) {
+ * ssize_t rc = -1;
+ */
+
+ rc = wrap_readlinkat(AT_FDCWD, path, buf, bufsiz);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/readlinkat.c b/ports/unix/guts/readlinkat.c
new file mode 100644
index 0000000..5282e2b
--- /dev/null
+++ b/ports/unix/guts/readlinkat.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static ssize_t
+ * wrap_readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
+ * ssize_t rc = -1;
+ */
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+ rc = real_readlink(path, buf, bufsiz);
+#else
+ rc = real_readlinkat(dirfd, path, buf, bufsiz);
+#endif
+
+ if (rc > 0) {
+ rc = pseudo_dechroot(buf, rc);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/realpath.c b/ports/unix/guts/realpath.c
new file mode 100644
index 0000000..8059f5e
--- /dev/null
+++ b/ports/unix/guts/realpath.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static char *
+ * wrap_realpath(const char *name, char *resolved_name) {
+ * char * rc = NULL;
+ */
+ char *rname = PSEUDO_ROOT_PATH(AT_FDCWD, name, 0);
+ ssize_t len;
+ if (!rname) {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
+ if ((len = strlen(rname)) >= pseudo_sys_path_max()) {
+ free(rname);
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
+ if (resolved_name) {
+ memcpy(resolved_name, rname, len + 1);
+ free(rname);
+ rc = resolved_name;
+ } else {
+ rc = rname;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/remove.c b/ports/unix/guts/remove.c
new file mode 100644
index 0000000..902a640
--- /dev/null
+++ b/ports/unix/guts/remove.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_remove(const char *path) {
+ * int rc = -1;
+ */
+ struct stat buf;
+ if (real_lstat(path, &buf) == -1) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (S_ISDIR(buf.st_mode)) {
+ rc = wrap_rmdir(path);
+ } else {
+ rc = wrap_unlink(path);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/rename.c b/ports/unix/guts/rename.c
new file mode 100644
index 0000000..04892c1
--- /dev/null
+++ b/ports/unix/guts/rename.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_rename(const char *oldpath, const char *newpath) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ struct stat oldbuf, newbuf;
+ int oldrc, newrc;
+ int save_errno;
+ int old_db_entry = 0;
+
+ pseudo_debug(2, "rename: %s->%s\n",
+ oldpath ? oldpath : "<nil>",
+ newpath ? newpath : "<nil>");
+
+ if (!oldpath || !newpath) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ save_errno = errno;
+
+ newrc = real_lstat(newpath, &newbuf);
+ oldrc = real_lstat(oldpath, &oldbuf);
+
+ errno = save_errno;
+
+ /* newpath must be removed. */
+ /* as with unlink, we have to mark that the file may get deleted */
+ msg = pseudo_client_op_plain(OP_MAY_UNLINK, 0, -1, -1, newpath, newrc ? NULL : &newbuf);
+ if (msg && msg->result == RESULT_SUCCEED)
+ old_db_entry = 1;
+ rc = real_rename(oldpath, newpath);
+ save_errno = errno;
+ if (old_db_entry) {
+ if (rc == -1) {
+ /* since we failed, that wasn't really unlinked -- put
+ * it back.
+ */
+ pseudo_client_op_plain(OP_CANCEL_UNLINK, 0, -1, -1, newpath, &newbuf);
+ } else {
+ /* confirm that the file was removed */
+ pseudo_client_op_plain(OP_DID_UNLINK, 0, -1, -1, newpath, &newbuf);
+ }
+ }
+ if (rc == -1) {
+ /* and we're done. */
+ errno = save_errno;
+ return rc;
+ }
+ save_errno = errno;
+ /* nothing to do for a "rename" of a link to itself */
+ if (newrc != -1 && oldrc != -1 &&
+ newbuf.st_dev == oldbuf.st_dev &&
+ newbuf.st_ino == oldbuf.st_ino) {
+ return rc;
+ }
+
+ /* rename(3) is not mv(1). rename(file, dir) fails; you must provide
+ * the corrected path yourself. You can rename over a directory only
+ * if the source is a directory. Symlinks are simply removed.
+ *
+ * If we got here, the real rename call succeeded. That means newpath
+ * has been unlinked and oldpath has been linked to it.
+ *
+ * There are a ton of special cases to error check. I don't check
+ * for any of them, because in every such case, the underlying rename
+ * failed, and there is nothing to do.
+ * The only tricky part is that, because we used to ignore symlinks,
+ * we may have to rename or remove directory trees even though in
+ * theory rename can never destroy a directory tree.
+ */
+ if (!old_db_entry) {
+ /* create an entry under the old name, which will then be
+ * renamed; this way, children would get renamed too, if there
+ * were any.
+ */
+ if (newrc == 0) {
+ if (newbuf.st_dev != oldbuf.st_dev) {
+ oldbuf.st_dev = newbuf.st_dev;
+ oldbuf.st_ino = newbuf.st_ino;
+ }
+ }
+ pseudo_debug(1, "creating new '%s' [%llu] to rename\n",
+ oldpath, (unsigned long long) oldbuf.st_ino);
+ pseudo_client_op_plain(OP_LINK, 0, -1, -1, oldpath, &oldbuf);
+ }
+ pseudo_client_op_plain(OP_RENAME, 0, -1, -1, newpath, &oldbuf, oldpath);
+
+ errno = save_errno;
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/renameat.c b/ports/unix/guts/renameat.c
new file mode 100644
index 0000000..c8203b7
--- /dev/null
+++ b/ports/unix/guts/renameat.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
+ * int rc = -1;
+ */
+
+ pseudo_diag("help! unimplemented renameat [%s -> %s].\n", oldpath, newpath);
+ rc = real_renameat(olddirfd, oldpath, newdirfd, newpath);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/rmdir.c b/ports/unix/guts/rmdir.c
new file mode 100644
index 0000000..7307fcd
--- /dev/null
+++ b/ports/unix/guts/rmdir.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_rmdir(const char *path) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ struct stat buf;
+ int save_errno;
+ int old_db_entry = 0;
+
+ rc = real_lstat(path, &buf);
+ if (rc == -1) {
+ return rc;
+ }
+ msg = pseudo_client_op_plain(OP_MAY_UNLINK, 0, -1, -1, path, &buf);
+ if (msg && msg->result == RESULT_SUCCEED)
+ old_db_entry = 1;
+ rc = real_rmdir(path);
+ if (old_db_entry) {
+ if (rc == -1) {
+ save_errno = errno;
+ pseudo_client_op_plain(OP_CANCEL_UNLINK, 0, -1, -1, path, &buf);
+ errno = save_errno;
+ } else {
+ pseudo_client_op_plain(OP_DID_UNLINK, 0, -1, -1, path, &buf);
+ }
+ } else {
+ pseudo_debug(1, "rmdir on <%s>, not in database, no effect.\n", path);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/symlink.c b/ports/unix/guts/symlink.c
new file mode 100644
index 0000000..487c135
--- /dev/null
+++ b/ports/unix/guts/symlink.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_symlink(const char *oldname, const char *newpath) {
+ * int rc = -1;
+ */
+
+ rc = wrap_symlinkat(oldname, AT_FDCWD, newpath);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/symlinkat.c b/ports/unix/guts/symlinkat.c
new file mode 100644
index 0000000..9912c31
--- /dev/null
+++ b/ports/unix/guts/symlinkat.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_symlinkat(const char *oldname, int dirfd, const char *newpath) {
+ * int rc = -1;
+ */
+ struct stat buf;
+ char *roldname = 0;
+
+ if (oldname[0] == '/' && pseudo_chroot_len && !pseudo_nosymlinkexp) {
+ size_t len = pseudo_chroot_len + strlen(oldname) + 1;
+ roldname = malloc(len);
+ snprintf(roldname, len, "%s%s", pseudo_chroot, oldname);
+ }
+
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+ rc = real_symlink(roldname ? roldname : oldname, newpath);
+#else
+ rc = real_symlinkat(roldname ? roldname : oldname, dirfd, newpath);
+#endif
+
+ if (rc == -1) {
+ free(roldname);
+ return rc;
+ }
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ rc = real_lstat(newpath, &buf);
+#else
+ rc = real___fxstatat(_STAT_VER, dirfd, newpath, &buf, AT_SYMLINK_NOFOLLOW);
+#endif
+ if (rc == -1) {
+ int save_errno = errno;
+ pseudo_diag("symlinkat: couldn't stat '%s' even though symlink creation succeeded (%s).\n",
+ newpath, strerror(errno));
+ errno = save_errno;
+ free(roldname);
+ return rc;
+ }
+ /* just record the entry */
+ pseudo_client_op_plain(OP_SYMLINK, 0, -1, dirfd, newpath, &buf);
+
+ free(roldname);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/tempnam.c b/ports/unix/guts/tempnam.c
new file mode 100644
index 0000000..9b0257f
--- /dev/null
+++ b/ports/unix/guts/tempnam.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static char *
+ * wrap_tempnam(const char *template, const char *pfx) {
+ * char * rc = NULL;
+ */
+ /* let gcc know we ignored these on purpose */
+ (void) template;
+ (void) pfx;
+ pseudo_diag("tempnam() is so ludicrously insecure as to defy implementation.");
+ errno = ENOMEM;
+ rc = NULL;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/tmpnam.c b/ports/unix/guts/tmpnam.c
new file mode 100644
index 0000000..3fece57
--- /dev/null
+++ b/ports/unix/guts/tmpnam.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static char *
+ * wrap_tmpnam(char *s) {
+ * char * rc = NULL;
+ */
+
+ /* let gcc know we're ignoring this */
+ (void) s;
+ pseudo_diag("tmpnam() is so ludicrously insecure as to defy implementation.");
+ errno = ENOMEM;
+ rc = NULL;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/truncate.c b/ports/unix/guts/truncate.c
new file mode 100644
index 0000000..6a19a50
--- /dev/null
+++ b/ports/unix/guts/truncate.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_truncate(const char *path, off_t length) {
+ * int rc = -1;
+ */
+
+ rc = real_truncate(path, length);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/unlink.c b/ports/unix/guts/unlink.c
new file mode 100644
index 0000000..d8a5d01
--- /dev/null
+++ b/ports/unix/guts/unlink.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_unlink(const char *path) {
+ * int rc = -1;
+ */
+
+ rc = wrap_unlinkat(AT_FDCWD, path, 0);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/unlinkat.c b/ports/unix/guts/unlinkat.c
new file mode 100644
index 0000000..7b51ab9
--- /dev/null
+++ b/ports/unix/guts/unlinkat.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_unlinkat(int dirfd, const char *path, int rflags) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ int save_errno;
+ struct stat buf;
+ int old_db_entry;
+
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+ if (rflags) {
+ /* the only supported flag is AT_REMOVEDIR. We'd never call
+ * with that flag unless the real AT functions exist, so
+ * something must have gone horribly wrong....
+ */
+ pseudo_diag("wrap_unlinkat called with flags (0x%x), path '%s'\n",
+ rflags, path ? path : "<nil>");
+ errno = ENOSYS;
+ return -1;
+ }
+#endif
+
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ rc = real_lstat(path, &buf);
+#else
+ rc = real___fxstatat(_STAT_VER, dirfd, path, &buf, AT_SYMLINK_NOFOLLOW);
+#endif
+ if (rc == -1) {
+ return rc;
+ }
+ msg = pseudo_client_op_plain(OP_MAY_UNLINK, 0, -1, dirfd, path, &buf);
+ if (msg && msg->result == RESULT_SUCCEED)
+ old_db_entry = 1;
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ rc = real_unlink(path);
+#else
+ rc = real_unlinkat(dirfd, path, rflags);
+#endif
+ if (old_db_entry) {
+ if (rc == -1) {
+ save_errno = errno;
+ pseudo_client_op_plain(OP_CANCEL_UNLINK, 0, -1, -1, path, &buf);
+ errno = save_errno;
+ } else {
+ pseudo_client_op_plain(OP_DID_UNLINK, 0, -1, -1, path, &buf);
+ }
+ } else {
+ pseudo_debug(1, "unlink on <%s>, not in database, no effect.\n", path);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/utime.c b/ports/unix/guts/utime.c
new file mode 100644
index 0000000..ff65237
--- /dev/null
+++ b/ports/unix/guts/utime.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_utime(const char *path, const struct utimbuf *buf) {
+ * int rc = -1;
+ */
+ rc = real_utime(path, buf);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/guts/utimes.c b/ports/unix/guts/utimes.c
new file mode 100644
index 0000000..69ad949
--- /dev/null
+++ b/ports/unix/guts/utimes.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_utimes(const char *path, const struct timeval *times) {
+ * int rc = -1;
+ */
+ rc = real_utimes(path, times);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/unix/wrapfuncs.in b/ports/unix/wrapfuncs.in
new file mode 100644
index 0000000..b0fdb2c
--- /dev/null
+++ b/ports/unix/wrapfuncs.in
@@ -0,0 +1,56 @@
+int creat(const char *path, mode_t mode);
+char *getcwd(char *buf, size_t size);
+char *getwd(char *buf);
+int close(int fd);
+int fchmod(int fd, mode_t mode);
+int fchown(int fd, uid_t owner, gid_t group);
+int lchown(const char *path, uid_t owner, gid_t group); /* flags=AT_SYMLINK_NOFOLLOW */
+int dup2(int oldfd, int newfd);
+int dup(int fd);
+int chdir(const char *path);
+int fchdir(int dirfd);
+int access(const char *path, int mode);
+FTS *fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)); /* inode64=1 */
+int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int nopenfd);
+int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int nopenfd, int flag);
+int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob);
+int lutimes(const char *path, const struct timeval *tv);
+char *mkdtemp(char *template);
+char *mktemp(char *template);
+long pathconf(const char *path, int name);
+char *realpath(const char *name, char *resolved_name);
+int remove(const char *path); /* flags=AT_SYMLINK_NOFOLLOW */
+DIR *opendir(const char *path);
+char *tempnam(const char *template, const char *pfx);
+char *tmpnam(char *s);
+int truncate(const char *path, off_t length);
+int utime(const char *path, const struct utimbuf *buf);
+int utimes(const char *path, const struct timeval *times);
+# needed because libc stdio does horrible things with inline asm syscalls
+FILE *fopen(const char *path, const char *mode);
+int fclose(FILE *fp);
+FILE *freopen(const char *path, const char *mode, FILE *stream);
+int chroot(const char *path);
+int acct(const char *path);
+int chmod(const char *path, mode_t mode);
+int chown(const char *path, uid_t owner, gid_t group);
+int fchmodat(int dirfd, const char *path, mode_t mode, int flags);
+int fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags);
+int link(const char *oldpath, const char *newpath); /* flags=AT_SYMLINK_NOFOLLOW */
+int mkdir(const char *path, mode_t mode); /* flags=AT_SYMLINK_NOFOLLOW */
+int mkdirat(int dirfd, const char *path, mode_t mode); /* flags=AT_SYMLINK_NOFOLLOW */
+int mkfifo(const char *path, mode_t mode); /* flags=AT_SYMLINK_NOFOLLOW */
+int mkfifoat(int dirfd, const char *path, mode_t mode); /* flags=AT_SYMLINK_NOFOLLOW */
+int mknod(const char *path, mode_t mode, dev_t dev); /* flags=AT_SYMLINK_NOFOLLOW */
+int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev); /* flags=AT_SYMLINK_NOFOLLOW */
+int mkstemp(char *template); /* flags=AT_SYMLINK_NOFOLLOW */
+int rename(const char *oldpath, const char *newpath); /* flags=AT_SYMLINK_NOFOLLOW */
+int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); /* flags=AT_SYMLINK_NOFOLLOW */
+int rmdir(const char *path); /* flags=AT_SYMLINK_NOFOLLOW */
+int symlink(const char *oldname, const char *newpath); /* flags=AT_SYMLINK_NOFOLLOW */
+int symlinkat(const char *oldname, int dirfd, const char *newpath); /* flags=AT_SYMLINK_NOFOLLOW */
+int unlink(const char *path); /* flags=AT_SYMLINK_NOFOLLOW */
+int unlinkat(int dirfd, const char *path, int rflags); /* flags=AT_SYMLINK_NOFOLLOW */
+# primarily for use with chroot()
+ssize_t readlink(const char *path, char *buf, size_t bufsiz); /* flags=AT_SYMLINK_NOFOLLOW */
+ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz); /* flags=AT_SYMLINK_NOFOLLOW */