aboutsummaryrefslogtreecommitdiffstats
path: root/ports
diff options
context:
space:
mode:
authorPeter Seebach <peter.seebach@windriver.com>2011-03-25 12:38:43 -0500
committerPeter Seebach <peter.seebach@windriver.com>2011-03-25 12:38:43 -0500
commit29e8b8a4cd8f7383c3d851b6255272f1c2a5d286 (patch)
treec9619032a670d06124ef45c392484f4a04f7d0f0 /ports
parent96d8e7ce8b483e5cafd0449b9735e4714f41f20b (diff)
downloadpseudo-29e8b8a4cd8f7383c3d851b6255272f1c2a5d286.tar.gz
pseudo-29e8b8a4cd8f7383c3d851b6255272f1c2a5d286.tar.bz2
pseudo-29e8b8a4cd8f7383c3d851b6255272f1c2a5d286.zip
Merge in ports work
This is a spiffied-up rebase of a bunch of intermediate changes, presented as a whole because it is, surprisingly, less confusing that way. The basic idea is to separate the guts code into categories ranging from generic stuff that can be the same everywhere and specific variants. The big scary one is the Darwin support, which actually seems to run okay on 64-bit OS X 10.6. (No other variants were tested.) The other example given is support for the old clone() syscall on RHEL 4, which affects some wrlinux use cases. There's a few minor cleanup bits here, such as a function with inconsistent calling conventions, but nothing really exciting.
Diffstat (limited to 'ports')
-rw-r--r--ports/common/guts/execl.c13
-rw-r--r--ports/common/guts/execle.c13
-rw-r--r--ports/common/guts/execlp.c13
-rw-r--r--ports/common/guts/execv.c36
-rw-r--r--ports/common/guts/execve.c37
-rw-r--r--ports/common/guts/execvp.c37
-rw-r--r--ports/common/guts/fork.c24
-rw-r--r--ports/common/pseudo_wrappers.c376
-rw-r--r--ports/common/subports8
-rw-r--r--ports/common/wrapfuncs.in7
-rw-r--r--ports/darwin/guts/COPYRIGHT17
-rw-r--r--ports/darwin/guts/fcntl.c46
-rw-r--r--ports/darwin/guts/fgetgrent_r.c13
-rw-r--r--ports/darwin/guts/fgetpwent_r.c13
-rw-r--r--ports/darwin/guts/fgetxattr.c13
-rw-r--r--ports/darwin/guts/flistxattr.c13
-rw-r--r--ports/darwin/guts/fsetxattr.c13
-rw-r--r--ports/darwin/guts/fstat.c27
-rw-r--r--ports/darwin/guts/getgrent_r.c13
-rw-r--r--ports/darwin/guts/getgrouplist.c42
-rw-r--r--ports/darwin/guts/getgroups.c22
-rw-r--r--ports/darwin/guts/getpwent_r.c13
-rw-r--r--ports/darwin/guts/getxattr.c13
-rw-r--r--ports/darwin/guts/listxattr.c13
-rw-r--r--ports/darwin/guts/lstat.c27
-rw-r--r--ports/darwin/guts/open.c49
-rw-r--r--ports/darwin/guts/scandir.c14
-rw-r--r--ports/darwin/guts/setxattr.c13
-rw-r--r--ports/darwin/guts/stat.c31
-rw-r--r--ports/darwin/portdefs.h10
-rw-r--r--ports/darwin/preports2
-rw-r--r--ports/darwin/pseudo_wrappers.c316
-rw-r--r--ports/darwin/subports3
-rw-r--r--ports/darwin/wrapfuncs.in25
-rw-r--r--ports/linux/guts/COPYRIGHT17
-rw-r--r--ports/linux/guts/__fxstat.c20
-rw-r--r--ports/linux/guts/__fxstat64.c30
-rw-r--r--ports/linux/guts/__fxstatat.c32
-rw-r--r--ports/linux/guts/__fxstatat64.c58
-rw-r--r--ports/linux/guts/__lxstat.c14
-rw-r--r--ports/linux/guts/__lxstat64.c14
-rw-r--r--ports/linux/guts/__openat64_2.c14
-rw-r--r--ports/linux/guts/__openat_2.c14
-rw-r--r--ports/linux/guts/__xmknod.c14
-rw-r--r--ports/linux/guts/__xmknodat.c73
-rw-r--r--ports/linux/guts/__xstat.c14
-rw-r--r--ports/linux/guts/__xstat64.c13
-rw-r--r--ports/linux/guts/canonicalize_file_name.c14
-rw-r--r--ports/linux/guts/creat64.c14
-rw-r--r--ports/linux/guts/eaccess.c14
-rw-r--r--ports/linux/guts/euidaccess.c14
-rw-r--r--ports/linux/guts/fcntl.c71
-rw-r--r--ports/linux/guts/fgetxattr.c18
-rw-r--r--ports/linux/guts/flistxattr.c17
-rw-r--r--ports/linux/guts/fopen64.c36
-rw-r--r--ports/linux/guts/fremovexattr.c16
-rw-r--r--ports/linux/guts/freopen64.c35
-rw-r--r--ports/linux/guts/fsetxattr.c19
-rw-r--r--ports/linux/guts/fstat.c13
-rw-r--r--ports/linux/guts/ftw64.c14
-rw-r--r--ports/linux/guts/get_current_dir_name.c18
-rw-r--r--ports/linux/guts/getgrent_r.c21
-rw-r--r--ports/linux/guts/getgrouplist.c42
-rw-r--r--ports/linux/guts/getgroups.c22
-rw-r--r--ports/linux/guts/getpw.c33
-rw-r--r--ports/linux/guts/getpwent_r.c21
-rw-r--r--ports/linux/guts/getresgid.c23
-rw-r--r--ports/linux/guts/getresuid.c23
-rw-r--r--ports/linux/guts/getxattr.c18
-rw-r--r--ports/linux/guts/glob64.c36
-rw-r--r--ports/linux/guts/lchown.c13
-rw-r--r--ports/linux/guts/lckpwdf.c32
-rw-r--r--ports/linux/guts/lgetxattr.c18
-rw-r--r--ports/linux/guts/listxattr.c17
-rw-r--r--ports/linux/guts/llistxattr.c17
-rw-r--r--ports/linux/guts/lremovexattr.c16
-rw-r--r--ports/linux/guts/lsetxattr.c19
-rw-r--r--ports/linux/guts/lstat.c13
-rw-r--r--ports/linux/guts/mkstemp64.c47
-rw-r--r--ports/linux/guts/nftw64.c14
-rw-r--r--ports/linux/guts/open.c14
-rw-r--r--ports/linux/guts/open64.c14
-rw-r--r--ports/linux/guts/openat.c67
-rw-r--r--ports/linux/guts/openat64.c14
-rw-r--r--ports/linux/guts/removexattr.c16
-rw-r--r--ports/linux/guts/scandir.c14
-rw-r--r--ports/linux/guts/scandir64.c14
-rw-r--r--ports/linux/guts/setfsgid.c19
-rw-r--r--ports/linux/guts/setfsuid.c19
-rw-r--r--ports/linux/guts/setgroups.c18
-rw-r--r--ports/linux/guts/setresgid.c37
-rw-r--r--ports/linux/guts/setresuid.c37
-rw-r--r--ports/linux/guts/setxattr.c19
-rw-r--r--ports/linux/guts/stat.c13
-rw-r--r--ports/linux/guts/truncate64.c14
-rw-r--r--ports/linux/guts/ulckpwdf.c16
-rw-r--r--ports/linux/newclone/guts/clone.c27
-rw-r--r--ports/linux/newclone/pseudo_wrappers.c69
-rw-r--r--ports/linux/newclone/wrapfuncs.in1
-rw-r--r--ports/linux/oldclone/guts/clone.c27
-rw-r--r--ports/linux/oldclone/pseudo_wrappers.c59
-rw-r--r--ports/linux/oldclone/wrapfuncs.in1
-rw-r--r--ports/linux/portdefs.h5
-rw-r--r--ports/linux/preports2
-rw-r--r--ports/linux/pseudo_wrappers.c18
-rw-r--r--ports/linux/subports27
-rw-r--r--ports/linux/wrapfuncs.in64
-rw-r--r--ports/uids_generic/guts/COPYRIGHT17
-rw-r--r--ports/uids_generic/guts/endgrent.c14
-rw-r--r--ports/uids_generic/guts/endpwent.c14
-rw-r--r--ports/uids_generic/guts/getegid.c14
-rw-r--r--ports/uids_generic/guts/geteuid.c14
-rw-r--r--ports/uids_generic/guts/getgid.c14
-rw-r--r--ports/uids_generic/guts/getgrent.c21
-rw-r--r--ports/uids_generic/guts/getgrgid.c21
-rw-r--r--ports/uids_generic/guts/getgrgid_r.c30
-rw-r--r--ports/uids_generic/guts/getgrnam.c23
-rw-r--r--ports/uids_generic/guts/getgrnam_r.c29
-rw-r--r--ports/uids_generic/guts/getpwent.c21
-rw-r--r--ports/uids_generic/guts/getpwnam.c21
-rw-r--r--ports/uids_generic/guts/getpwnam_r.c28
-rw-r--r--ports/uids_generic/guts/getpwuid.c21
-rw-r--r--ports/uids_generic/guts/getpwuid_r.c28
-rw-r--r--ports/uids_generic/guts/getuid.c14
-rw-r--r--ports/uids_generic/guts/setegid.c20
-rw-r--r--ports/uids_generic/guts/seteuid.c20
-rw-r--r--ports/uids_generic/guts/setgid.c27
-rw-r--r--ports/uids_generic/guts/setgrent.c14
-rw-r--r--ports/uids_generic/guts/setpwent.c14
-rw-r--r--ports/uids_generic/guts/setregid.c30
-rw-r--r--ports/uids_generic/guts/setreuid.c30
-rw-r--r--ports/uids_generic/guts/setuid.c27
-rw-r--r--ports/uids_generic/wrapfuncs.in25
-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
189 files changed, 5230 insertions, 0 deletions
diff --git a/ports/common/guts/execl.c b/ports/common/guts/execl.c
new file mode 100644
index 0000000..ce908ed
--- /dev/null
+++ b/ports/common/guts/execl.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int execl(const char *file, const char *arg, va_list ap)
+ * int rc = -1;
+ */
+
+ rc = real_execl(file, arg, ap);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/common/guts/execle.c b/ports/common/guts/execle.c
new file mode 100644
index 0000000..68d8bba
--- /dev/null
+++ b/ports/common/guts/execle.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int execle(const char *file, const char *arg, va_list ap)
+ * int rc = -1;
+ */
+
+ rc = real_execle(file, arg, ap);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/common/guts/execlp.c b/ports/common/guts/execlp.c
new file mode 100644
index 0000000..d357986
--- /dev/null
+++ b/ports/common/guts/execlp.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int execlp(const char *file, const char *arg, va_list ap)
+ * int rc = -1;
+ */
+
+ rc = real_execlp(file, arg, ap);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/common/guts/execv.c b/ports/common/guts/execv.c
new file mode 100644
index 0000000..15ad51e
--- /dev/null
+++ b/ports/common/guts/execv.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_execv(const char *file, char *const *argv) {
+ * int rc = -1;
+ */
+ /* note: we don't canonicalize this, because we are intentionally
+ * NOT redirecting execs into the chroot environment. If you try
+ * to execute /bin/sh, you get the actual /bin/sh, not
+ * <CHROOT>/bin/sh. This allows use of basic utilities. This
+ * design will likely be revisited.
+ */
+ if (antimagic == 0) {
+ char *path_guess = pseudo_exec_path(file, 0);
+ pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0);
+ free(path_guess);
+ }
+
+ if (!pseudo_get_value("PSEUDO_RELOADED"))
+ pseudo_setupenv();
+ else {
+ pseudo_setupenv();
+ pseudo_dropenv();
+ }
+
+ /* if exec() fails, we may end up taking signals unexpectedly...
+ * not much we can do about that.
+ */
+ sigprocmask(SIG_SETMASK, &pseudo_saved_sigmask, NULL);
+ rc = real_execv(file, argv);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/common/guts/execve.c b/ports/common/guts/execve.c
new file mode 100644
index 0000000..a47b9a7
--- /dev/null
+++ b/ports/common/guts/execve.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_execve(const char *file, char *const *argv, char *const *envp) {
+ * int rc = -1;
+ */
+ char * const *new_environ;
+ /* note: we don't canonicalize this, because we are intentionally
+ * NOT redirecting execs into the chroot environment. If you try
+ * to execute /bin/sh, you get the actual /bin/sh, not
+ * <CHROOT>/bin/sh. This allows use of basic utilities. This
+ * design will likely be revisited.
+ */
+ if (antimagic == 0) {
+ char *path_guess = pseudo_exec_path(file, 0);
+ pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0);
+ free(path_guess);
+ }
+
+ if (!pseudo_get_value("PSEUDO_RELOADED"))
+ new_environ = pseudo_setupenvp(envp);
+ else {
+ new_environ = pseudo_setupenvp(envp);
+ new_environ = pseudo_dropenvp(new_environ);
+ }
+
+ /* if exec() fails, we may end up taking signals unexpectedly...
+ * not much we can do about that.
+ */
+ sigprocmask(SIG_SETMASK, &pseudo_saved_sigmask, NULL);
+ rc = real_execve(file, argv, new_environ);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/common/guts/execvp.c b/ports/common/guts/execvp.c
new file mode 100644
index 0000000..419f41b
--- /dev/null
+++ b/ports/common/guts/execvp.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_execvp(const char *file, char *const *argv) {
+ * int rc = -1;
+ */
+
+ /* note: we don't canonicalize this, because we are intentionally
+ * NOT redirecting execs into the chroot environment. If you try
+ * to execute /bin/sh, you get the actual /bin/sh, not
+ * <CHROOT>/bin/sh. This allows use of basic utilities. This
+ * design will likely be revisited.
+ */
+ if (antimagic == 0) {
+ char *path_guess = pseudo_exec_path(file, 1);
+ pseudo_client_op(OP_EXEC, PSA_EXEC, -1, -1, path_guess, 0);
+ free(path_guess);
+ }
+
+ if (!pseudo_get_value("PSEUDO_RELOADED"))
+ pseudo_setupenv();
+ else {
+ pseudo_setupenv();
+ pseudo_dropenv();
+ }
+
+ /* if exec() fails, we may end up taking signals unexpectedly...
+ * not much we can do about that.
+ */
+ sigprocmask(SIG_SETMASK, &pseudo_saved_sigmask, NULL);
+ rc = real_execvp(file, argv);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/common/guts/fork.c b/ports/common/guts/fork.c
new file mode 100644
index 0000000..76cac6f
--- /dev/null
+++ b/ports/common/guts/fork.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_fork(void) {
+ * int rc = -1;
+ */
+ rc = real_fork();
+ /* special case: we may want to enable or disable
+ * pseudo in the child process
+ */
+ if (rc == 0) {
+ if (!pseudo_get_value("PSEUDO_RELOADED")) {
+ pseudo_setupenv();
+ pseudo_reinit_libpseudo();
+ } else {
+ pseudo_setupenv();
+ pseudo_dropenv();
+ }
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/common/pseudo_wrappers.c b/ports/common/pseudo_wrappers.c
new file mode 100644
index 0000000..2cfc400
--- /dev/null
+++ b/ports/common/pseudo_wrappers.c
@@ -0,0 +1,376 @@
+/* these aren't used, but the wrapper table isn't happy unless they
+ * exist
+ */
+static int
+wrap_execl(const char *file, const char *arg, va_list ap) {
+ (void) file;
+ (void) arg;
+ (void) ap;
+ return 0;
+}
+
+static int
+wrap_execle(const char *file, const char *arg, va_list ap) {
+ (void) file;
+ (void) arg;
+ (void) ap;
+ return 0;
+}
+
+static int
+wrap_execlp(const char *file, const char *arg, va_list ap) {
+ (void) file;
+ (void) arg;
+ (void) ap;
+ return 0;
+}
+
+static char **
+execl_to_v(va_list ap, const char *argv0, char *const **envp) {
+ size_t i = 0;
+ size_t alloc_size = 256;
+
+ char **argv = malloc((sizeof *argv) * alloc_size);
+
+ if (!argv) {
+ pseudo_debug(1, "execl failed: couldn't allocate memory for %lu arguments\n",
+ (unsigned long) alloc_size);
+ return NULL;
+ }
+ argv[i++] = (char *) argv0;
+
+ while (argv[i-1]) {
+ argv[i++] = va_arg(ap, char *const);
+ if (i > alloc_size - 1) {
+ alloc_size = alloc_size + 256;
+ argv = realloc(argv, (sizeof *argv) * alloc_size);
+ if (!argv) {
+ pseudo_debug(1, "execl failed: couldn't allocate memory for %lu arguments\n",
+ (unsigned long) alloc_size);
+ return NULL;
+ }
+ }
+ }
+ if (envp) {
+ *envp = va_arg(ap, char **);
+ }
+ return argv;
+}
+
+/* The following wrappers require Special Handling */
+
+int
+execl(const char *file, const char *arg, ...) {
+ sigset_t saved;
+ va_list ap;
+ char **argv;
+
+ int rc = -1;
+
+ if (!pseudo_check_wrappers()) {
+ /* rc was initialized to the "failure" value */
+ pseudo_enosys("execl");
+ return rc;
+ }
+
+ va_start(ap, arg);
+ argv = execl_to_v(ap, arg, 0);
+ va_end(ap);
+ if (!argv) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ pseudo_debug(4, "called: execl\n");
+ pseudo_sigblock(&saved);
+ if (pseudo_getlock()) {
+ errno = EBUSY;
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ return -1;
+ }
+
+ int save_errno;
+
+ /* exec*() use this to restore the sig mask */
+ pseudo_saved_sigmask = saved;
+ rc = wrap_execv(file, argv);
+
+ save_errno = errno;
+ pseudo_droplock();
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ pseudo_debug(4, "completed: execl\n");
+ errno = save_errno;
+ free(argv);
+ return rc;
+}
+
+int
+execlp(const char *file, const char *arg, ...) {
+ sigset_t saved;
+ va_list ap;
+ char **argv;
+
+ int rc = -1;
+
+ if (!pseudo_check_wrappers()) {
+ /* rc was initialized to the "failure" value */
+ pseudo_enosys("execlp");
+ return rc;
+ }
+
+ va_start(ap, arg);
+ argv = execl_to_v(ap, arg, 0);
+ va_end(ap);
+ if (!argv) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ pseudo_debug(4, "called: execlp\n");
+ pseudo_sigblock(&saved);
+ if (pseudo_getlock()) {
+ errno = EBUSY;
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ return -1;
+ }
+
+ int save_errno;
+
+ /* exec*() use this to restore the sig mask */
+ pseudo_saved_sigmask = saved;
+ rc = wrap_execvp(file, argv);
+
+ save_errno = errno;
+ pseudo_droplock();
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ pseudo_debug(4, "completed: execlp\n");
+ errno = save_errno;
+ free(argv);
+ return rc;
+}
+
+int
+execle(const char *file, const char *arg, ...) {
+ sigset_t saved;
+ va_list ap;
+ char **argv;
+ char **envp;
+
+ int rc = -1;
+
+ if (!pseudo_check_wrappers()) {
+ /* rc was initialized to the "failure" value */
+ pseudo_enosys("execle");
+ return rc;
+ }
+
+ va_start(ap, arg);
+ argv = execl_to_v(ap, arg, (char *const **)&envp);
+ va_end(ap);
+ if (!argv) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ pseudo_debug(4, "called: execle\n");
+ pseudo_sigblock(&saved);
+ if (pseudo_getlock()) {
+ errno = EBUSY;
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ return -1;
+ }
+
+ int save_errno;
+
+ /* exec*() use this to restore the sig mask */
+ pseudo_saved_sigmask = saved;
+ rc = wrap_execve(file, argv, envp);
+
+ save_errno = errno;
+ pseudo_droplock();
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ pseudo_debug(4, "completed: execle\n");
+ errno = save_errno;
+ free(argv);
+ return rc;
+}
+
+int
+execv(const char *file, char *const *argv) {
+ sigset_t saved;
+
+ int rc = -1;
+
+ if (!pseudo_check_wrappers() || !real_execv) {
+ /* rc was initialized to the "failure" value */
+ pseudo_enosys("execv");
+ return rc;
+ }
+
+ pseudo_debug(4, "called: execv\n");
+ pseudo_sigblock(&saved);
+ if (pseudo_getlock()) {
+ errno = EBUSY;
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ return -1;
+ }
+
+ int save_errno;
+
+ /* exec*() use this to restore the sig mask */
+ pseudo_saved_sigmask = saved;
+ rc = wrap_execv(file, argv);
+
+ save_errno = errno;
+ pseudo_droplock();
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ pseudo_debug(4, "completed: execv\n");
+ errno = save_errno;
+ return rc;
+}
+
+int
+execve(const char *file, char *const *argv, char *const *envp) {
+ sigset_t saved;
+
+ int rc = -1;
+
+ if (!pseudo_check_wrappers() || !real_execve) {
+ /* rc was initialized to the "failure" value */
+ pseudo_enosys("execve");
+ return rc;
+ }
+
+ pseudo_debug(4, "called: execve\n");
+ pseudo_sigblock(&saved);
+ if (pseudo_getlock()) {
+ errno = EBUSY;
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ return -1;
+ }
+
+ int save_errno;
+
+ /* exec*() use this to restore the sig mask */
+ pseudo_saved_sigmask = saved;
+ rc = wrap_execve(file, argv, envp);
+
+ save_errno = errno;
+ pseudo_droplock();
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ pseudo_debug(4, "completed: execve\n");
+ errno = save_errno;
+ return rc;
+}
+
+int
+execvp(const char *file, char *const *argv) {
+ sigset_t saved;
+
+ int rc = -1;
+
+ if (!pseudo_check_wrappers() || !real_execvp) {
+ /* rc was initialized to the "failure" value */
+ pseudo_enosys("execvp");
+ return rc;
+ }
+
+ pseudo_debug(4, "called: execvp\n");
+ pseudo_sigblock(&saved);
+ if (pseudo_getlock()) {
+ errno = EBUSY;
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ return -1;
+ }
+
+ int save_errno;
+
+ /* exec*() use this to restore the sig mask */
+ pseudo_saved_sigmask = saved;
+ rc = wrap_execvp(file, argv);
+
+ save_errno = errno;
+ pseudo_droplock();
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ pseudo_debug(4, "completed: execvp\n");
+ errno = save_errno;
+ return rc;
+}
+
+int
+fork(void) {
+ sigset_t saved;
+
+ int rc = -1;
+
+ if (!pseudo_check_wrappers() || !real_fork) {
+ /* rc was initialized to the "failure" value */
+ pseudo_enosys("fork");
+ return rc;
+ }
+
+ pseudo_debug(4, "called: fork\n");
+ pseudo_sigblock(&saved);
+ if (pseudo_getlock()) {
+ errno = EBUSY;
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ return -1;
+ }
+
+ int save_errno;
+
+ rc = wrap_fork();
+
+ save_errno = errno;
+
+ pseudo_droplock();
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ pseudo_debug(4, "completed: fork\n");
+ errno = save_errno;
+ return rc;
+}
+
+int
+vfork(void) {
+ /* we don't provide support for the distinct semantics
+ * of vfork()
+ */
+ return fork();
+}
+
+static int
+wrap_execv(const char *file, char *const *argv) {
+ int rc = -1;
+
+#include "guts/execv.c"
+
+ return rc;
+}
+
+static int
+wrap_execve(const char *file, char *const *argv, char *const *envp) {
+ int rc = -1;
+
+#include "guts/execve.c"
+
+ return rc;
+}
+
+static int
+wrap_execvp(const char *file, char *const *argv) {
+ int rc = -1;
+
+#include "guts/execvp.c"
+
+ return rc;
+}
+
+static int
+wrap_fork(void) {
+ int rc = -1;
+
+#include "guts/fork.c"
+
+ return rc;
+}
+
diff --git a/ports/common/subports b/ports/common/subports
new file mode 100644
index 0000000..e2aac56
--- /dev/null
+++ b/ports/common/subports
@@ -0,0 +1,8 @@
+#!/bin/sh
+case $(uname -s) in
+Linux) echo "linux";;
+Darwin) echo "darwin";;
+*) echo >&2 "Unknown result from uname -s: %(uname -s). Aborting."
+ exit 1
+ ;;
+esac
diff --git a/ports/common/wrapfuncs.in b/ports/common/wrapfuncs.in
new file mode 100644
index 0000000..17440f9
--- /dev/null
+++ b/ports/common/wrapfuncs.in
@@ -0,0 +1,7 @@
+int execlp(const char *file, const char *arg, ...); /* hand_wrapped=1 */
+int execl(const char *file, const char *arg, ...); /* hand_wrapped=1 */
+int execle(const char *file, const char *arg, ...); /* hand_wrapped=1 */
+int execv(const char *file, char *const *argv); /* hand_wrapped=1 */
+int execve(const char *file, char *const *argv, char *const *envp); /* hand_wrapped=1 */
+int execvp(const char *file, char *const *argv); /* hand_wrapped=1 */
+int fork(void); /* hand_wrapped=1 */
diff --git a/ports/darwin/guts/COPYRIGHT b/ports/darwin/guts/COPYRIGHT
new file mode 100644
index 0000000..c96e1b1
--- /dev/null
+++ b/ports/darwin/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/darwin/guts/fcntl.c b/ports/darwin/guts/fcntl.c
new file mode 100644
index 0000000..ef42b33
--- /dev/null
+++ b/ports/darwin/guts/fcntl.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int fcntl(int fd, int cmd, ... { struct flock *lock })
+ * int rc = -1;
+ */
+ int save_errno;
+ long long flag = 0;
+ void *ptr = 0;
+ off_t off = 0;
+
+ va_start(ap, cmd);
+ flag = va_arg(ap, long long);
+ va_end(ap);
+ rc = real_fcntl(fd, cmd, flag);
+
+ switch (cmd) {
+ case F_DUPFD:
+#ifdef F_DUPFD_CLOEXEC
+ /* it doesn't exist now, but if I take this out they'll add it
+ * just to mess with me.
+ */
+ case F_DUPFD_CLOEXEC:
+#endif
+ /* actually do something */
+ save_errno = errno;
+ if (rc != -1) {
+ pseudo_debug(2, "fcntl_dup: %d->%d\n", fd, rc);
+ pseudo_client_op(OP_DUP, 0, fd, rc, 0, 0);
+ }
+ errno = save_errno;
+ break;
+ default:
+ /* nothing to do, we hope */
+ break;
+ }
+
+ save_errno = errno;
+ pseudo_debug(3, "fcntl(fd %d, cmd %d, %llx) => %d (%s)\n",
+ fd, cmd, flag, rc, strerror(errno));
+ errno = save_errno;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/fgetgrent_r.c b/ports/darwin/guts/fgetgrent_r.c
new file mode 100644
index 0000000..e760cdd
--- /dev/null
+++ b/ports/darwin/guts/fgetgrent_r.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int fgetgrent_r(FILE *fp, struct group*gbuf, char *buf, size_t buflen, struct group **gbufp)
+ * int rc = -1;
+ */
+
+ rc = real_fgetgrent_r(fp, gbuf, buf, buflen, gbufp);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/fgetpwent_r.c b/ports/darwin/guts/fgetpwent_r.c
new file mode 100644
index 0000000..cfea5b8
--- /dev/null
+++ b/ports/darwin/guts/fgetpwent_r.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int fgetpwent_r(FILE *fp, struct passwd *pbuf, char *buf, size_t buflen, struct passwd **pbufp)
+ * int rc = -1;
+ */
+
+ rc = real_fgetpwent_r(fp, pbuf, buf, buflen, pbufp);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/fgetxattr.c b/ports/darwin/guts/fgetxattr.c
new file mode 100644
index 0000000..1cd8904
--- /dev/null
+++ b/ports/darwin/guts/fgetxattr.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size, u_int32_t position, int options)
+ * ssize_t rc = -1;
+ */
+
+ rc = real_fgetxattr(filedes, name, value, size, position, options);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/flistxattr.c b/ports/darwin/guts/flistxattr.c
new file mode 100644
index 0000000..7575f28
--- /dev/null
+++ b/ports/darwin/guts/flistxattr.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * ssize_t flistxattr(int filedes, char *list, size_t size, int options)
+ * ssize_t rc = -1;
+ */
+
+ rc = real_flistxattr(filedes, list, size, options);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/fsetxattr.c b/ports/darwin/guts/fsetxattr.c
new file mode 100644
index 0000000..541569a
--- /dev/null
+++ b/ports/darwin/guts/fsetxattr.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int fsetxattr(int filedes, const char *name, const void *value, size_t size, u_int32_t position, int options)
+ * int rc = -1;
+ */
+
+ rc = real_fsetxattr(filedes, name, value, size, position, options);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/fstat.c b/ports/darwin/guts/fstat.c
new file mode 100644
index 0000000..7695147
--- /dev/null
+++ b/ports/darwin/guts/fstat.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int fstat(int fd, struct stat *buf)
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+
+ rc = real_fstat(fd, buf);
+
+ if (rc == -1) {
+ return rc;
+ }
+
+ /* query database
+ * note that symlink canonicalizing is now automatic, so we
+ * don't need to check for a symlink on this end
+ */
+ msg = pseudo_client_op(OP_FSTAT, 0, fd, -1, 0, buf);
+ if (msg && msg->result == RESULT_SUCCEED) {
+ pseudo_stat_msg(buf, msg);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/getgrent_r.c b/ports/darwin/guts/getgrent_r.c
new file mode 100644
index 0000000..9d5db5a
--- /dev/null
+++ b/ports/darwin/guts/getgrent_r.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp)
+ * int rc = -1;
+ */
+
+ rc = real_getgrent_r(gbuf, buf, buflen, gbufp);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/getgrouplist.c b/ports/darwin/guts/getgrouplist.c
new file mode 100644
index 0000000..85fccc9
--- /dev/null
+++ b/ports/darwin/guts/getgrouplist.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getgrouplist(const char *name, int basegid, int *groups, int *ngroups) {
+ * int rc = -1;
+ */
+
+ int found = 0;
+ int found_group = 0;
+ char buf[PSEUDO_PWD_MAX];
+ struct group grp, *gbuf = &grp;
+
+ setgrent();
+ while ((rc = wrap_getgrent_r(gbuf, buf, PSEUDO_PWD_MAX, &gbuf)) == 0) {
+ int i = 0;
+ for (i = 0; gbuf->gr_mem[i]; ++i) {
+ if (!strcmp(gbuf->gr_mem[i], name)) {
+ if (found < *ngroups)
+ groups[found] = gbuf->gr_gid;
+ ++found;
+ if ((int) gbuf->gr_gid == basegid)
+ found_group = 1;
+ }
+ }
+ }
+ endgrent();
+ if (!found_group) {
+ if (found < *ngroups)
+ groups[found] = basegid;
+ ++found;
+ }
+ if (found >= *ngroups)
+ rc = -1;
+ else
+ rc = found;
+ *ngroups = found;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/getgroups.c b/ports/darwin/guts/getgroups.c
new file mode 100644
index 0000000..3cbeb76
--- /dev/null
+++ b/ports/darwin/guts/getgroups.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getgroups(int size, gid_t *list) {
+ * int rc = -1;
+ */
+ struct passwd *p = wrap_getpwuid(wrap_getuid());
+ int oldsize = size;
+
+ if (p) {
+ rc = wrap_getgrouplist(p->pw_name, wrap_getgid(), (int *) list, &size);
+ if (oldsize == 0 || size <= oldsize)
+ rc = size;
+ } else {
+ errno = ENOENT;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/getpwent_r.c b/ports/darwin/guts/getpwent_r.c
new file mode 100644
index 0000000..3de41b9
--- /dev/null
+++ b/ports/darwin/guts/getpwent_r.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp)
+ * int rc = -1;
+ */
+
+ rc = real_getpwent_r(pwbuf, buf, buflen, pwbufp);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/getxattr.c b/ports/darwin/guts/getxattr.c
new file mode 100644
index 0000000..16f0993
--- /dev/null
+++ b/ports/darwin/guts/getxattr.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * ssize_t getxattr(const char *pathname, const char *name, void *value, size_t size, u_int32_t position, int options)
+ * ssize_t rc = -1;
+ */
+
+ rc = real_getxattr(pathname, name, value, size, position, options);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/listxattr.c b/ports/darwin/guts/listxattr.c
new file mode 100644
index 0000000..0bba451
--- /dev/null
+++ b/ports/darwin/guts/listxattr.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * ssize_t listxattr(const char *pathname, char *list, size_t size, int options)
+ * ssize_t rc = -1;
+ */
+
+ rc = real_listxattr(pathname, list, size, options);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/lstat.c b/ports/darwin/guts/lstat.c
new file mode 100644
index 0000000..01e0f30
--- /dev/null
+++ b/ports/darwin/guts/lstat.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int lstat(const char *path, struct stat *buf)
+ * int rc = -1;
+ */
+
+ pseudo_msg_t *msg;
+
+ rc = real_lstat(path, buf);
+ if (rc == -1) {
+ return rc;
+ }
+
+ /* query database
+ * note that symlink canonicalizing is now automatic, so we
+ * don't need to check for a symlink on this end
+ */
+ msg = pseudo_client_op(OP_STAT, 0, -1, -1, path, buf);
+ if (msg && msg->result == RESULT_SUCCEED) {
+ pseudo_stat_msg(buf, msg);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/open.c b/ports/darwin/guts/open.c
new file mode 100644
index 0000000..64cb6ad
--- /dev/null
+++ b/ports/darwin/guts/open.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int open(const char *path, int flags, ... { int mode })
+ * int rc = -1;
+ */
+
+ struct stat buf;
+ int existed = 1;
+ int save_errno;
+
+ /* if a creation has been requested, check whether file exists */
+ if (flags & O_CREAT) {
+ save_errno = errno;
+ rc = real_stat(path, &buf);
+ existed = (rc != -1);
+ if (!existed)
+ pseudo_debug(2, "open_creat: %s -> 0%o\n", path, mode);
+ errno = save_errno;
+ }
+
+ /* because we are not actually root, secretly mask in 0700 to the
+ * underlying mode
+ */
+ rc = real_open(path, flags, PSEUDO_FS_MODE(mode));
+ save_errno = errno;
+
+ if (rc != -1) {
+ int stat_rc;
+ stat_rc = real_stat(path, &buf);
+
+ if (stat_rc != -1) {
+ buf.st_mode = PSEUDO_DB_MODE(buf.st_mode, mode);
+ if (!existed) {
+ pseudo_client_op(OP_CREAT, 0, -1, -1, path, &buf);
+ }
+ pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, -1, path, &buf);
+ } else {
+ pseudo_debug(1, "open (fd %d, path %s, flags %d) succeeded, but stat failed (%s).\n",
+ rc, path, flags, strerror(errno));
+ pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, -1, path, 0);
+ }
+ errno = save_errno;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/scandir.c b/ports/darwin/guts/scandir.c
new file mode 100644
index 0000000..6492b1b
--- /dev/null
+++ b/ports/darwin/guts/scandir.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_scandir(const char *path, struct dirent ***namelist, int (*filter)(struct dirent *), int (*compar)(const void *, const void *)) {
+ * int rc = -1;
+ */
+
+ rc = real_scandir(path, namelist, filter, compar);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/setxattr.c b/ports/darwin/guts/setxattr.c
new file mode 100644
index 0000000..3c8fd3d
--- /dev/null
+++ b/ports/darwin/guts/setxattr.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int setxattr(const char *pathname, const char *name, const void *value, size_t size, u_int32_t position, int options)
+ * int rc = -1;
+ */
+
+ rc = real_setxattr(pathname, name, value, size, position, options);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/guts/stat.c b/ports/darwin/guts/stat.c
new file mode 100644
index 0000000..1e1cf67
--- /dev/null
+++ b/ports/darwin/guts/stat.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int stat(const char *path, struct stat *buf)
+ * int rc = -1;
+ */
+
+ pseudo_msg_t *msg;
+ int save_errno;
+
+ rc = real_stat(path, buf);
+ if (rc == -1) {
+ return rc;
+ }
+ save_errno = errno;
+
+ /* query database
+ * note that symlink canonicalizing is now automatic, so we
+ * don't need to check for a symlink on this end
+ */
+ msg = pseudo_client_op(OP_STAT, 0, -1, AT_FDCWD, path, buf);
+ if (msg) {
+ pseudo_stat_msg(buf, msg);
+ }
+
+ errno = save_errno;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/darwin/portdefs.h b/ports/darwin/portdefs.h
new file mode 100644
index 0000000..f27e28d
--- /dev/null
+++ b/ports/darwin/portdefs.h
@@ -0,0 +1,10 @@
+#define PRELINK_LIBRARIES "DYLD_INSERT_LIBRARIES"
+#define PRELINK_PATH "DYLD_LIBRARY_PATH"
+#define PSEUDO_STATBUF_64 0
+#define PSEUDO_STATBUF struct stat
+#define PSEUDO_LINKPATH_SEPARATOR ":"
+/* hackery to allow sneaky things to be done with getgrent() */
+extern int pseudo_host_etc_passwd_fd;
+extern int pseudo_host_etc_group_fd;
+extern FILE *pseudo_host_etc_passwd_file;
+extern FILE *pseudo_host_etc_group_file;
diff --git a/ports/darwin/preports b/ports/darwin/preports
new file mode 100644
index 0000000..a996c69
--- /dev/null
+++ b/ports/darwin/preports
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo "unix" "uids_generic"
diff --git a/ports/darwin/pseudo_wrappers.c b/ports/darwin/pseudo_wrappers.c
new file mode 100644
index 0000000..36d9172
--- /dev/null
+++ b/ports/darwin/pseudo_wrappers.c
@@ -0,0 +1,316 @@
+/*
+ * pseudo_wrappers.c, darwin pseudo wrappers
+ *
+ * Copyright (c) 2008-2011 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
+ *
+ */
+/* there's no fgetgrent_r or fgetpwent_r in Darwin */
+int
+pseudo_getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) {
+ /* note that we don't wrap fgetpwent_r, since there's no path
+ * references in it.
+ */
+ if (!pseudo_pwd) {
+ errno = ENOENT;
+ return -1;
+ }
+ return fgetpwent_r(pseudo_pwd, pwbuf, buf, buflen, pwbufp);
+}
+
+int
+pseudo_getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
+ /* note that we don't wrap fgetgrent_r, since there's no path
+ * references in it.
+ */
+ if (!pseudo_grp) {
+ errno = ENOENT;
+ return -1;
+ }
+ return fgetgrent_r(pseudo_grp, gbuf, buf, buflen, gbufp);
+}
+
+#define PLENTY_LONG 2048
+/* the original uid/gid code for Linux was written in terms of the
+ * fget*ent_r() functions... which Darwin doesn't have. But wait! They're
+ * actually pretty easy to implement.
+ */
+int
+pseudo_fgetgrent_r(FILE *fp, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
+ char linebuf[PLENTY_LONG] = { 0 };
+ char *s, *t, *u;
+ size_t max_members;
+ char **members;
+ size_t member = 0;
+ long started_at = -1;
+ gid_t gid;
+ int error = ENOENT;
+ size_t len;
+
+ /* any early exit should set *gbufp to NULL */
+ if (gbufp)
+ *gbufp = NULL;
+
+ if (!gbuf || !fp || !buf)
+ goto error_out;
+
+ if (fp == pseudo_host_etc_group_file) {
+ struct group *g;
+ pseudo_antimagic();
+ g = getgrent();
+ pseudo_magic();
+ if (g) {
+ char *s = linebuf;
+ s += snprintf(linebuf, PLENTY_LONG,
+ "%s:%s:%ld:",
+ g->gr_name,
+ g->gr_passwd,
+ (long) g->gr_gid);
+ if (g->gr_mem) {
+ int i;
+ for (i = 0; g->gr_mem[i]; ++i) {
+ s += snprintf(s,
+ PLENTY_LONG - (s - linebuf),
+ "%s,",
+ g->gr_mem[i]);
+ }
+ if (s[-1] == ',')
+ --s;
+ }
+ strcpy(s, "\n");
+ } else {
+ goto error_out;
+ }
+ } else {
+ started_at = ftell(fp);
+ if (started_at == -1) {
+ goto error_out;
+ }
+ s = fgets(linebuf, PLENTY_LONG, fp);
+ if (!s) {
+ goto error_out;
+ }
+ }
+ /* fgets will have stored a '\0' if there was no error; if there
+ * was an error, though, linebuf was initialized to all zeroes so
+ * the string is null-terminated anyway...
+ */
+ len = strlen(linebuf);
+ if (len > buflen) {
+ error = ERANGE;
+ goto error_out;
+ }
+ memcpy(buf, linebuf, len);
+ /* round up to 8, hope for the best? */
+ len = len + 8 + (((unsigned long long) (buf + len)) % 8);
+ members = (char **) (buf + len);
+ if (len >= buflen) {
+ error = ERANGE;
+ goto error_out;
+ }
+ /* this is how many pointers we have room for... */
+ max_members = (buflen - len) / sizeof(*members);
+
+ t = buf;
+ /* yes, I can assume that Darwin has strsep() */
+ s = strsep(&t, ":");
+ if (!s) {
+ goto error_out;
+ }
+ gbuf->gr_name = s;
+ s = strsep(&t, ":");
+ if (!s) {
+ goto error_out;
+ }
+ gbuf->gr_passwd = s;
+ s = strsep(&t, ":");
+ if (!s) {
+ goto error_out;
+ }
+ gid = (gid_t) strtol(s, &u, 10);
+ /* should be a null byte, otherwise we didn't get a valid number */
+ if (*u)
+ goto error_out;
+ gbuf->gr_gid = gid;
+
+ /* now, s points to a comma-separated list of members, which we
+ * want to stash pointers to in 'members'.
+ */
+ s = strsep(&t, ":");
+ t = s;
+ while ((s = strsep(&t, ",")) != NULL) {
+ if (*s) {
+ if (member + 1 > max_members) {
+ errno = ERANGE;
+ goto error_out;
+ }
+ members[member++] = s;
+ }
+ }
+ if (member + 1 > max_members) {
+ errno = ERANGE;
+ goto error_out;
+ }
+ members[member++] = NULL;
+ *gbufp = gbuf;
+ return 0;
+
+error_out:
+ if (started_at != -1)
+ fseek(fp, started_at, SEEK_SET);
+ return error;
+ return -1;
+}
+
+int
+pseudo_fgetpwent_r(FILE *fp, struct passwd *pbuf, char *buf, size_t buflen, struct passwd **pbufp) {
+ char linebuf[PLENTY_LONG] = { 0 };
+ char *s, *t, *u;
+ long started_at = -1;
+ __darwin_time_t timestamp;
+ uid_t uid;
+ gid_t gid;
+ int error = ENOENT;
+ size_t len;
+
+ /* any early exit should set *gbufp to NULL */
+ if (pbufp)
+ *pbufp = NULL;
+
+ if (!pbuf || !fp || !buf)
+ goto error_out;
+
+ if (fp == pseudo_host_etc_passwd_file) {
+ struct passwd *p;
+
+ pseudo_antimagic();
+ p = getpwent();
+ pseudo_magic();
+ if (p) {
+ snprintf(linebuf, PLENTY_LONG,
+ "%s:%s:%ld:%ld:%s:%ld:%ld:%s:%s:%s\n",
+ p->pw_name,
+ p->pw_passwd,
+ (long) p->pw_uid,
+ (long) p->pw_gid,
+ p->pw_class,
+ (long) p->pw_change,
+ (long) p->pw_expire,
+ p->pw_gecos,
+ p->pw_dir,
+ p->pw_shell);
+ } else {
+ goto error_out;
+ }
+ } else {
+ started_at = ftell(fp);
+ if (started_at == -1) {
+ goto error_out;
+ }
+ s = fgets(linebuf, PLENTY_LONG, fp);
+ if (!s) {
+ goto error_out;
+ }
+ }
+ /* fgets will have stored a '\0' if there was no error; if there
+ * was an error, though, linebuf was initialized to all zeroes so
+ * the string is null-terminated anyway...
+ */
+ len = strlen(linebuf);
+ if (len > buflen) {
+ error = ERANGE;
+ goto error_out;
+ }
+ if (linebuf[len - 1] == '\n') {
+ linebuf[len - 1] = '\0';
+ --len;
+ }
+ memcpy(buf, linebuf, len);
+
+ t = buf;
+ /* yes, I can assume that Darwin has strsep() */
+ s = strsep(&t, ":");
+ if (!s) {
+ goto error_out;
+ }
+ pbuf->pw_name = s;
+
+ s = strsep(&t, ":");
+ if (!s)
+ goto error_out;
+ pbuf->pw_passwd = s;
+
+ s = strsep(&t, ":");
+ if (!s)
+ goto error_out;
+ uid = (uid_t) strtol(s, &u, 10);
+ /* should be a null byte, otherwise we didn't get a valid number */
+ if (*u)
+ goto error_out;
+ pbuf->pw_uid = uid;
+
+ s = strsep(&t, ":");
+ if (!s)
+ goto error_out;
+ gid = (gid_t) strtol(s, &u, 10);
+ /* should be a null byte, otherwise we didn't get a valid number */
+ if (*u)
+ goto error_out;
+ pbuf->pw_gid = gid;
+
+ s = strsep(&t, ":");
+ if (!s)
+ goto error_out;
+ pbuf->pw_class = s;
+
+ s = strsep(&t, ":");
+ if (!s)
+ goto error_out;
+ timestamp = (__darwin_time_t) strtol(s, &u, 10);
+ /* should be a null byte, otherwise we didn't get a valid number */
+ if (*u)
+ goto error_out;
+ pbuf->pw_change = timestamp;
+
+ timestamp = (__darwin_time_t) strtol(s, &u, 10);
+ /* should be a null byte, otherwise we didn't get a valid number */
+ if (*u)
+ goto error_out;
+ pbuf->pw_expire = timestamp;
+
+ s = strsep(&t, ":");
+ if (!s)
+ goto error_out;
+ pbuf->pw_gecos = s;
+
+ s = strsep(&t, ":");
+ if (!s)
+ goto error_out;
+ pbuf->pw_dir = s;
+
+ s = strsep(&t, ":");
+ if (!s)
+ goto error_out;
+ pbuf->pw_shell = s;
+
+ *pbufp = pbuf;
+ return 0;
+
+error_out:
+ if (started_at != -1)
+ fseek(fp, started_at, SEEK_SET);
+ return error;
+ return -1;
+}
diff --git a/ports/darwin/subports b/ports/darwin/subports
new file mode 100644
index 0000000..57bdd6d
--- /dev/null
+++ b/ports/darwin/subports
@@ -0,0 +1,3 @@
+#!/bin/sh
+# no subports at this time
+exit 0
diff --git a/ports/darwin/wrapfuncs.in b/ports/darwin/wrapfuncs.in
new file mode 100644
index 0000000..39d9893
--- /dev/null
+++ b/ports/darwin/wrapfuncs.in
@@ -0,0 +1,25 @@
+# On Darwin, mode_t promotes to int, so you have to use int for va_arg
+int open(const char *path, int flags, ...{int mode}); /* flags=0 */
+int stat(const char *path, struct stat *buf); /* inode64=1 */
+int lstat(const char *path, struct stat *buf); /* flags=AT_SYMLINK_NOFOLLOW, inode64=1 */
+int fstat(int fd, struct stat *buf); /* inode64=1 */
+int fcntl(int fd, int cmd, ...{struct flock *lock});
+# just so we know the inums of symlinks
+# for emulation of passwd utilities
+int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups);
+# we use "pathname" to avoid canonicalizing paths, because these functions are
+# unimplemented
+ssize_t getxattr(const char *pathname, const char *name, void *value, size_t size, u_int32_t position, int options);
+ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size, u_int32_t position, int options);
+ssize_t listxattr(const char *pathname, char *list, size_t size, int options);
+ssize_t flistxattr(int filedes, char *list, size_t size, int options);
+int setxattr(const char *pathname, const char *name, const void *value, size_t size, u_int32_t position, int options);
+int fsetxattr(int filedes, const char *name, const void *value, size_t size, u_int32_t position, int options);
+# local color UIDs
+int getgrouplist(const char *name, int basegid, int *groups, int *ngroups);
+int scandir(const char *path, struct dirent ***namelist, int (*filter)(struct dirent *), int (*compar)());
+int getgroups(int size, gid_t *list);
+int fgetgrent_r(FILE *fp, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp); /* real_func=pseudo_fgetgrent_r */
+int fgetpwent_r(FILE *fp, struct passwd *pbuf, char *buf, size_t buflen, struct passwd **pbufp); /* real_func=pseudo_fgetpwent_r */
+int getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp); /* real_func=pseudo_getpwent_r */
+int getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp); /* real_func=pseudo_getgrent_r */
diff --git a/ports/linux/guts/COPYRIGHT b/ports/linux/guts/COPYRIGHT
new file mode 100644
index 0000000..c96e1b1
--- /dev/null
+++ b/ports/linux/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/linux/guts/__fxstat.c b/ports/linux/guts/__fxstat.c
new file mode 100644
index 0000000..db9716b
--- /dev/null
+++ b/ports/linux/guts/__fxstat.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int
+ * wrap___fxstat(int ver, int fd, struct stat *buf) {
+ * int rc = -1;
+ */
+
+ struct stat64 buf64;
+ /* populate buffer with complete data */
+ real___fxstat(ver, fd, buf);
+ /* obtain fake data */
+ rc = wrap___fxstat64(ver, fd, &buf64);
+ /* overwrite */
+ pseudo_stat32_from64(buf, &buf64);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/__fxstat64.c b/ports/linux/guts/__fxstat64.c
new file mode 100644
index 0000000..92c8219
--- /dev/null
+++ b/ports/linux/guts/__fxstat64.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int
+ * wrap___fxstat64(int ver, int fd, struct stat64 *buf) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ int save_errno;
+
+ rc = real___fxstat64(ver, fd, buf);
+ save_errno = errno;
+ if (rc == -1) {
+ return rc;
+ }
+ if (ver != _STAT_VER) {
+ pseudo_debug(1, "version mismatch: got stat version %d, only supporting %d\n", ver, _STAT_VER);
+ errno = save_errno;
+ return rc;
+ }
+ msg = pseudo_client_op(OP_FSTAT, 0, fd, -1, 0, buf);
+ if (msg && msg->result == RESULT_SUCCEED) {
+ pseudo_stat_msg(buf, msg);
+ }
+
+ errno = save_errno;
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/__fxstatat.c b/ports/linux/guts/__fxstatat.c
new file mode 100644
index 0000000..94c5ff6
--- /dev/null
+++ b/ports/linux/guts/__fxstatat.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap___fxstatat(int ver, int dirfd, const char *path, struct stat *buf, int flags) {
+ * int rc = -1;
+ */
+
+ struct stat64 buf64;
+ /* populate buffer with complete data */
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+ if (flags & AT_SYMLINK_NOFOLLOW) {
+ rc = real___lxstat(ver, path, buf);
+ } else {
+ rc = real___xstat(ver, path, buf);
+ }
+#else
+ real___fxstatat(ver, dirfd, path, buf, flags);
+#endif
+ /* obtain fake data */
+ rc = wrap___fxstatat64(ver, dirfd, path, &buf64, flags);
+ /* overwrite */
+ pseudo_stat32_from64(buf, &buf64);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/__fxstatat64.c b/ports/linux/guts/__fxstatat64.c
new file mode 100644
index 0000000..f8a9298
--- /dev/null
+++ b/ports/linux/guts/__fxstatat64.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap___fxstatat64(int ver, int dirfd, const char *path, struct stat64 *buf, int flags) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ int save_errno;
+
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+#endif
+ if (flags & AT_SYMLINK_NOFOLLOW) {
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ rc = real___lxstat64(ver, path, buf);
+#else
+ rc = real___fxstatat64(ver, dirfd, path, buf, flags);
+#endif
+ if (rc == -1) {
+ return rc;
+ }
+ } else {
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ rc = real___xstat64(ver, path, buf);
+#else
+ rc = real___fxstatat64(ver, dirfd, path, buf, flags);
+#endif
+ if (rc == -1) {
+ return rc;
+ }
+ }
+ save_errno = errno;
+
+ if (ver != _STAT_VER) {
+ pseudo_debug(1, "version mismatch: got stat version %d, only supporting %d\n", ver, _STAT_VER);
+ errno = save_errno;
+ return rc;
+ }
+
+ /* query database
+ * note that symlink canonicalizing is now automatic, so we
+ * don't need to check for a symlink on this end
+ */
+ msg = pseudo_client_op(OP_STAT, 0, -1, dirfd, path, buf);
+ if (msg) {
+ pseudo_stat_msg(buf, msg);
+ }
+
+ errno = save_errno;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/__lxstat.c b/ports/linux/guts/__lxstat.c
new file mode 100644
index 0000000..32b0301
--- /dev/null
+++ b/ports/linux/guts/__lxstat.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap___lxstat(int ver, const char *path, struct stat *buf) {
+ * int rc = -1;
+ */
+
+ rc = wrap___fxstatat(ver, AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
+
+/*
+ * }
+ */
diff --git a/ports/linux/guts/__lxstat64.c b/ports/linux/guts/__lxstat64.c
new file mode 100644
index 0000000..ac1f782
--- /dev/null
+++ b/ports/linux/guts/__lxstat64.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap___lxstat64(int ver, const char *path, struct stat64 *buf) {
+ * int rc = -1;
+ */
+
+ rc = wrap___fxstatat64(ver, AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
+
+/*
+ * }
+ */
diff --git a/ports/linux/guts/__openat64_2.c b/ports/linux/guts/__openat64_2.c
new file mode 100644
index 0000000..8772115
--- /dev/null
+++ b/ports/linux/guts/__openat64_2.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap___openat64_2(int dirfd, const char *path, int flags) {
+ * int rc = -1;
+ */
+
+ rc = wrap_openat(dirfd, path, flags, O_LARGEFILE);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/__openat_2.c b/ports/linux/guts/__openat_2.c
new file mode 100644
index 0000000..33ed620
--- /dev/null
+++ b/ports/linux/guts/__openat_2.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap___openat_2(int dirfd, const char *path, int flags) {
+ * int rc = -1;
+ */
+
+ rc = wrap_openat(dirfd, path, flags, 0);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/__xmknod.c b/ports/linux/guts/__xmknod.c
new file mode 100644
index 0000000..fa31b66
--- /dev/null
+++ b/ports/linux/guts/__xmknod.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap___xmknod(int ver, const char *path, mode_t mode, dev_t *dev) {
+ * int rc = -1;
+ */
+
+ rc = wrap___xmknodat(ver, AT_FDCWD, path, mode, dev);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/__xmknodat.c b/ports/linux/guts/__xmknodat.c
new file mode 100644
index 0000000..49b2f8f
--- /dev/null
+++ b/ports/linux/guts/__xmknodat.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap___xmknodat(int ver, int dirfd, const char *path, mode_t mode, dev_t *dev) {
+ * int rc = -1;
+ */
+ pseudo_msg_t *msg;
+ struct stat64 buf;
+
+ /* we don't use underlying call, so _ver is irrelevant to us */
+ (void) ver;
+
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+ rc = real___xstat64(_STAT_VER, path, &buf);
+#else
+ rc = real___fxstatat64(_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;
+ }
+ if (!dev) {
+ errno = EINVAL;
+ 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___fxstat64(_STAT_VER, 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(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/linux/guts/__xstat.c b/ports/linux/guts/__xstat.c
new file mode 100644
index 0000000..ec10abb
--- /dev/null
+++ b/ports/linux/guts/__xstat.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap___xstat(int ver, const char *path, struct stat *buf) {
+ * int rc = -1;
+ */
+
+ rc = wrap___fxstatat(ver, AT_FDCWD, path, buf, 0);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/__xstat64.c b/ports/linux/guts/__xstat64.c
new file mode 100644
index 0000000..ed62e7e
--- /dev/null
+++ b/ports/linux/guts/__xstat64.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap___xstat64(int ver, const char *path, struct stat64 *buf) {
+ * int rc = -1;
+ */
+ rc = wrap___fxstatat64(ver, AT_FDCWD, path, buf, 0);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/canonicalize_file_name.c b/ports/linux/guts/canonicalize_file_name.c
new file mode 100644
index 0000000..9a04f33
--- /dev/null
+++ b/ports/linux/guts/canonicalize_file_name.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static char *
+ * wrap_canonicalize_file_name(const char *filename) {
+ * char * rc = NULL;
+ */
+
+ rc = wrap_realpath(filename, NULL);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/creat64.c b/ports/linux/guts/creat64.c
new file mode 100644
index 0000000..2d2fc27
--- /dev/null
+++ b/ports/linux/guts/creat64.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_creat64(const char *path, ...mode_t mode) {
+ * int rc = -1;
+ */
+
+ rc = wrap_openat(AT_FDCWD, path, O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE, mode);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/eaccess.c b/ports/linux/guts/eaccess.c
new file mode 100644
index 0000000..e2119cc
--- /dev/null
+++ b/ports/linux/guts/eaccess.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_eaccess(const char *path, int mode) {
+ * int rc = -1;
+ */
+
+ rc = wrap_access(path, mode);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/euidaccess.c b/ports/linux/guts/euidaccess.c
new file mode 100644
index 0000000..85433a8
--- /dev/null
+++ b/ports/linux/guts/euidaccess.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_euidaccess(const char *path, int mode) {
+ * int rc = -1;
+ */
+
+ rc = wrap_access(path, mode);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/fcntl.c b/ports/linux/guts/fcntl.c
new file mode 100644
index 0000000..2e3e96d
--- /dev/null
+++ b/ports/linux/guts/fcntl.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_fcntl(int fd, int cmd, ...struct flock *lock) {
+ * int rc = -1;
+ */
+ long arg;
+ int save_errno;
+
+ /* we don't know whether we need lock or arg; grab both, which
+ * should be safe enough on Linuxy systems. */
+ va_start(ap, cmd);
+ arg = va_arg(ap, long);
+ va_end(ap);
+
+ switch (cmd) {
+ case F_DUPFD:
+#ifdef F_DUPFD_CLOEXEC
+ case F_DUPFD_CLOEXEC:
+#endif
+ /* actually do something */
+ rc = real_fcntl(fd, cmd, arg);
+ save_errno = errno;
+ if (rc != -1) {
+ pseudo_debug(2, "fcntl_dup: %d->%d\n", fd, rc);
+ pseudo_client_op(OP_DUP, 0, fd, rc, 0, 0);
+ }
+ errno = save_errno;
+ break;
+ /* no argument: */
+ case F_GETFD:
+ case F_GETFL:
+ case F_GETOWN:
+ case F_GETSIG:
+ case F_GETLEASE:
+ rc = real_fcntl(fd, cmd);
+ break;
+ /* long argument */
+ case F_SETFD:
+ case F_SETFL:
+ case F_SETOWN:
+ case F_SETSIG:
+ case F_SETLEASE:
+ case F_NOTIFY:
+ rc = real_fcntl(fd, cmd, arg);
+ break;
+ /* struct flock * argument */
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ rc = real_fcntl(fd, cmd, lock);
+ break;
+#if defined(F_GETLK64) && (F_GETLK64 != F_GETLK)
+ /* the cast is safe, all struct pointers must smell the same */
+ case F_GETLK64:
+ case F_SETLK64:
+ case F_SETLKW64:
+ rc = real_fcntl(fd, cmd, (struct flock64 *) lock);
+ break;
+#endif
+ default:
+ pseudo_diag("unknown fcntl argument %d, assuming long argument.\n",
+ cmd);
+ rc = real_fcntl(fd, cmd, arg);
+ break;
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/fgetxattr.c b/ports/linux/guts/fgetxattr.c
new file mode 100644
index 0000000..9d33643
--- /dev/null
+++ b/ports/linux/guts/fgetxattr.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size)
+ * ssize_t rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) filedes;
+ (void) name;
+ (void) value;
+ (void) size;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/flistxattr.c b/ports/linux/guts/flistxattr.c
new file mode 100644
index 0000000..77db021
--- /dev/null
+++ b/ports/linux/guts/flistxattr.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * ssize_t flistxattr(int filedes, char *list, size_t size)
+ * ssize_t rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) filedes;
+ (void) list;
+ (void) size;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/fopen64.c b/ports/linux/guts/fopen64.c
new file mode 100644
index 0000000..b2724de
--- /dev/null
+++ b/ports/linux/guts/fopen64.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static FILE *
+ * wrap_fopen64(const char *path, const char *mode) {
+ * FILE * rc = 0;
+ */
+ struct stat64 buf;
+ int save_errno;
+
+ int existed = (real___xstat64(_STAT_VER, path, &buf) != -1);
+
+ rc = real_fopen64(path, mode);
+ save_errno = errno;
+
+ if (rc) {
+ int fd = fileno(rc);
+
+ pseudo_debug(2, "fopen64 '%s': fd %d <FILE %p>\n", path, fd, (void *) rc);
+ if (real___fxstat64(_STAT_VER, fd, &buf) != -1) {
+ if (!existed) {
+ pseudo_client_op(OP_CREAT, 0, -1, -1, path, &buf);
+ }
+ pseudo_client_op(OP_OPEN, pseudo_access_fopen(mode), fd, -1, path, &buf);
+ } else {
+ pseudo_debug(1, "fopen64 (fd %d) succeeded, but fstat failed (%s).\n",
+ fd, strerror(errno));
+ pseudo_client_op(OP_OPEN, pseudo_access_fopen(mode), fd, -1, path, 0);
+ }
+ errno = save_errno;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/fremovexattr.c b/ports/linux/guts/fremovexattr.c
new file mode 100644
index 0000000..529a9de
--- /dev/null
+++ b/ports/linux/guts/fremovexattr.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int fremovexattr(int filedes, const char *name)
+ * int rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) filedes;
+ (void) name;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/freopen64.c b/ports/linux/guts/freopen64.c
new file mode 100644
index 0000000..b8e576b
--- /dev/null
+++ b/ports/linux/guts/freopen64.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static FILE *
+ * wrap_freopen64(const char *path, const char *mode, FILE *stream) {
+ * FILE * rc = NULL;
+ */
+ struct stat64 buf;
+ int save_errno;
+ int existed = (real___xstat64(_STAT_VER, path, &buf) != -1);
+
+ rc = real_freopen64(path, mode, stream);
+ save_errno = errno;
+
+ if (rc) {
+ int fd = fileno(rc);
+
+ pseudo_debug(2, "freopen64 '%s': fd %d\n", path, fd);
+ if (real___fxstat64(_STAT_VER, fd, &buf) != -1) {
+ if (!existed) {
+ pseudo_client_op(OP_CREAT, 0, -1, -1, path, &buf);
+ }
+ pseudo_client_op(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(OP_OPEN, pseudo_access_fopen(mode), fd, -1, path, 0);
+ }
+ errno = save_errno;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/fsetxattr.c b/ports/linux/guts/fsetxattr.c
new file mode 100644
index 0000000..3c56ddd
--- /dev/null
+++ b/ports/linux/guts/fsetxattr.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags)
+ * int rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) filedes;
+ (void) name;
+ (void) value;
+ (void) size;
+ (void) flags;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/fstat.c b/ports/linux/guts/fstat.c
new file mode 100644
index 0000000..2cf2787
--- /dev/null
+++ b/ports/linux/guts/fstat.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int fstat(int fd, struct stat *buf)
+ * int rc = -1;
+ */
+
+ rc = wrap___fxstat(_STAT_VER, fd, buf);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/ftw64.c b/ports/linux/guts/ftw64.c
new file mode 100644
index 0000000..a375fbf
--- /dev/null
+++ b/ports/linux/guts/ftw64.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_ftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int), int nopenfd) {
+ * int rc = -1;
+ */
+
+ rc = real_ftw64(path, fn, nopenfd);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/get_current_dir_name.c b/ports/linux/guts/get_current_dir_name.c
new file mode 100644
index 0000000..e07a6ee
--- /dev/null
+++ b/ports/linux/guts/get_current_dir_name.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static char *
+ * wrap_get_current_dir_name(void) {
+ * char * rc = NULL;
+ */
+
+ pseudo_debug(3, "get_current_dir_name (getcwd)\n");
+ /* this relies on a Linux extension, but we dutifully
+ * emulated that extension.
+ */
+ rc = wrap_getcwd(NULL, 0);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/getgrent_r.c b/ports/linux/guts/getgrent_r.c
new file mode 100644
index 0000000..b04373d
--- /dev/null
+++ b/ports/linux/guts/getgrent_r.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010-2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
+ * int rc = -1;
+ */
+
+ /* note that we don't wrap fgetgrent_r, since there's no path
+ * references in it.
+ */
+ if (!pseudo_grp) {
+ errno = ENOENT;
+ return -1;
+ }
+ rc = fgetgrent_r(pseudo_grp, gbuf, buf, buflen, gbufp);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/getgrouplist.c b/ports/linux/guts/getgrouplist.c
new file mode 100644
index 0000000..3489ec9
--- /dev/null
+++ b/ports/linux/guts/getgrouplist.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) {
+ * int rc = -1;
+ */
+
+ int found = 0;
+ int found_group = 0;
+ char buf[PSEUDO_PWD_MAX];
+ struct group grp, *gbuf = &grp;
+
+ setgrent();
+ while ((rc = wrap_getgrent_r(gbuf, buf, PSEUDO_PWD_MAX, &gbuf)) == 0) {
+ int i = 0;
+ for (i = 0; gbuf->gr_mem[i]; ++i) {
+ if (!strcmp(gbuf->gr_mem[i], user)) {
+ if (found < *ngroups)
+ groups[found] = gbuf->gr_gid;
+ ++found;
+ if (gbuf->gr_gid == group)
+ found_group = 1;
+ }
+ }
+ }
+ endgrent();
+ if (!found_group) {
+ if (found < *ngroups)
+ groups[found] = group;
+ ++found;
+ }
+ if (found >= *ngroups)
+ rc = -1;
+ else
+ rc = found;
+ *ngroups = found;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/getgroups.c b/ports/linux/guts/getgroups.c
new file mode 100644
index 0000000..afb9662
--- /dev/null
+++ b/ports/linux/guts/getgroups.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getgroups(int size, gid_t *list) {
+ * int rc = -1;
+ */
+ struct passwd *p = wrap_getpwuid(wrap_getuid());
+ int oldsize = size;
+
+ if (p) {
+ rc = wrap_getgrouplist(p->pw_name, wrap_getgid(), list, &size);
+ if (oldsize == 0 || size <= oldsize)
+ rc = size;
+ } else {
+ errno = ENOENT;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/getpw.c b/ports/linux/guts/getpw.c
new file mode 100644
index 0000000..62b44da
--- /dev/null
+++ b/ports/linux/guts/getpw.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getpw(uid_t uid, char *buf) {
+ * int rc = -1;
+ */
+ static struct passwd pwd;
+ static char pwbuf[PSEUDO_PWD_MAX];
+ struct passwd *pwp;
+
+ pseudo_diag("warning: unsafe getpw() called. hoping buf has at least %d chars.\n",
+ PSEUDO_PWD_MAX);
+ rc = wrap_getpwuid_r(uid, &pwd, pwbuf, PSEUDO_PWD_MAX, &pwp);
+ /* different error return conventions */
+ if (rc != 0) {
+ errno = rc;
+ rc = -1;
+ } else {
+ snprintf(buf, PSEUDO_PWD_MAX, "%s:%s:%d:%d:%s:%s:%s",
+ pwd.pw_name,
+ pwd.pw_passwd,
+ pwd.pw_uid,
+ pwd.pw_gid,
+ pwd.pw_gecos,
+ pwd.pw_dir,
+ pwd.pw_shell);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/getpwent_r.c b/ports/linux/guts/getpwent_r.c
new file mode 100644
index 0000000..4fd9cc0
--- /dev/null
+++ b/ports/linux/guts/getpwent_r.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010-2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) {
+ * int rc = -1;
+ */
+
+ /* note that we don't wrap fgetpwent_r, since there's no path
+ * references in it.
+ */
+ if (!pseudo_pwd) {
+ errno = ENOENT;
+ return -1;
+ }
+ rc = fgetpwent_r(pseudo_pwd, pwbuf, buf, buflen, pwbufp);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/getresgid.c b/ports/linux/guts/getresgid.c
new file mode 100644
index 0000000..13551a4
--- /dev/null
+++ b/ports/linux/guts/getresgid.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) {
+ * int rc = -1;
+ */
+ if (rgid)
+ *rgid = pseudo_rgid;
+ if (egid)
+ *egid = pseudo_egid;
+ if (sgid)
+ *sgid = pseudo_sgid;
+ if (rgid && egid && sgid) {
+ rc = 0;
+ } else {
+ rc = -1;
+ errno = EFAULT;
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/getresuid.c b/ports/linux/guts/getresuid.c
new file mode 100644
index 0000000..2e47520
--- /dev/null
+++ b/ports/linux/guts/getresuid.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) {
+ * int rc = -1;
+ */
+ if (ruid)
+ *ruid = pseudo_ruid;
+ if (euid)
+ *euid = pseudo_euid;
+ if (suid)
+ *suid = pseudo_suid;
+ if (ruid && euid && suid) {
+ rc = 0;
+ } else {
+ rc = -1;
+ errno = EFAULT;
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/getxattr.c b/ports/linux/guts/getxattr.c
new file mode 100644
index 0000000..fe8912d
--- /dev/null
+++ b/ports/linux/guts/getxattr.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * ssize_t getxattr(const char *pathname, const char *name, void *value, size_t size)
+ * ssize_t rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) pathname;
+ (void) name;
+ (void) value;
+ (void) size;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/glob64.c b/ports/linux/guts/glob64.c
new file mode 100644
index 0000000..ccac6e4
--- /dev/null
+++ b/ports/linux/guts/glob64.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_glob64(const char *pattern, int flags, int (*errfunc)(const char *, int), glob64_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_glob64(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/linux/guts/lchown.c b/ports/linux/guts/lchown.c
new file mode 100644
index 0000000..4eb1202
--- /dev/null
+++ b/ports/linux/guts/lchown.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_lchown(const char *path, uid_t owner, gid_t group) {
+ */
+
+ rc = wrap_fchownat(AT_FDCWD, path, owner, group, AT_SYMLINK_NOFOLLOW);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/lckpwdf.c b/ports/linux/guts/lckpwdf.c
new file mode 100644
index 0000000..b452ec0
--- /dev/null
+++ b/ports/linux/guts/lckpwdf.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_lckpwdf(void) {
+ * int rc = -1;
+ */
+ rc = pseudo_pwd_lck_open();
+ if (rc != -1) {
+ struct flock lck = {
+ .l_type = F_RDLCK,
+ .l_whence = SEEK_SET,
+ .l_start = 0,
+ .l_len = 1
+ };
+ /* I don't really care whether this works. */
+ fcntl(rc, F_SETFD, FD_CLOEXEC);
+ /* Now lock it. */
+ alarm(15); /* magic number from man page */
+ rc = fcntl(rc, F_SETLKW, &lck);
+ alarm(0);
+ if (rc == -1) {
+ int save_errno = errno;
+ pseudo_pwd_lck_close();
+ errno = save_errno;
+ }
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/lgetxattr.c b/ports/linux/guts/lgetxattr.c
new file mode 100644
index 0000000..404211f
--- /dev/null
+++ b/ports/linux/guts/lgetxattr.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * ssize_t lgetxattr(const char *pathname, const char *name, void *value, size_t size)
+ * ssize_t rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) pathname;
+ (void) name;
+ (void) value;
+ (void) size;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/listxattr.c b/ports/linux/guts/listxattr.c
new file mode 100644
index 0000000..1b0b5e7
--- /dev/null
+++ b/ports/linux/guts/listxattr.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * ssize_t listxattr(const char *pathname, char *list, size_t size)
+ * ssize_t rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) pathname;
+ (void) list;
+ (void) size;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/llistxattr.c b/ports/linux/guts/llistxattr.c
new file mode 100644
index 0000000..a33f970
--- /dev/null
+++ b/ports/linux/guts/llistxattr.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * ssize_t llistxattr(const char *pathname, char *list, size_t size)
+ * ssize_t rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) pathname;
+ (void) list;
+ (void) size;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/lremovexattr.c b/ports/linux/guts/lremovexattr.c
new file mode 100644
index 0000000..38429da
--- /dev/null
+++ b/ports/linux/guts/lremovexattr.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int lremovexattr(const char *pathname, const char *name)
+ * int rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) pathname;
+ (void) name;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/lsetxattr.c b/ports/linux/guts/lsetxattr.c
new file mode 100644
index 0000000..140ae8d
--- /dev/null
+++ b/ports/linux/guts/lsetxattr.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int lsetxattr(const char *pathname, const char *name, const void *value, size_t size, int flags)
+ * int rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) pathname;
+ (void) name;
+ (void) value;
+ (void) size;
+ (void) flags;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/lstat.c b/ports/linux/guts/lstat.c
new file mode 100644
index 0000000..19c202f
--- /dev/null
+++ b/ports/linux/guts/lstat.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int lstat(const char *path, struct stat *buf)
+ * int rc = -1;
+ */
+
+ rc = wrap___fxstatat(_STAT_VER, AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/mkstemp64.c b/ports/linux/guts/mkstemp64.c
new file mode 100644
index 0000000..def4126
--- /dev/null
+++ b/ports/linux/guts/mkstemp64.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_mkstemp64(char *template) {
+ * int rc = -1;
+ */
+ struct stat64 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_mkstemp64(tmp_template);
+
+ if (rc != -1) {
+ save_errno = errno;
+
+ if (real___fxstat64(_STAT_VER, rc, &buf) != -1) {
+ pseudo_client_op(OP_CREAT, 0, -1, -1, tmp_template, &buf);
+ pseudo_client_op(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(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/linux/guts/nftw64.c b/ports/linux/guts/nftw64.c
new file mode 100644
index 0000000..82571cd
--- /dev/null
+++ b/ports/linux/guts/nftw64.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_nftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int, struct FTW *), int nopenfd, int flag) {
+ * int rc = -1;
+ */
+
+ rc = real_nftw64(path, fn, nopenfd, flag);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/open.c b/ports/linux/guts/open.c
new file mode 100644
index 0000000..0a0596c
--- /dev/null
+++ b/ports/linux/guts/open.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_open(const char *path, int flags, ...mode_t mode) {
+ * int rc = -1;
+ */
+
+ return wrap_openat(AT_FDCWD, path, flags, mode);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/open64.c b/ports/linux/guts/open64.c
new file mode 100644
index 0000000..adeb885
--- /dev/null
+++ b/ports/linux/guts/open64.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_open64(const char *path, int flags, ...mode_t mode) {
+ * int rc = -1;
+ */
+
+ rc = wrap_openat(AT_FDCWD, path, flags, mode | O_LARGEFILE);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/openat.c b/ports/linux/guts/openat.c
new file mode 100644
index 0000000..c245796
--- /dev/null
+++ b/ports/linux/guts/openat.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_openat(int dirfd, const char *path, int flags, ...mode_t mode) {
+ * int rc = -1;
+ */
+ struct stat64 buf;
+ int existed = 1;
+ int save_errno;
+
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ if (dirfd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+#endif
+ /* if a creation has been requested, check whether file exists */
+ if (flags & O_CREAT) {
+ save_errno = errno;
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ rc = real___xstat64(_STAT_VER, path, &buf);
+#else
+ rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, 0);
+#endif
+ existed = (rc != -1);
+ if (!existed)
+ pseudo_debug(2, "openat_creat: %s -> 0%o\n", path, mode);
+ errno = save_errno;
+ }
+
+ /* because we are not actually root, secretly mask in 0700 to the
+ * underlying mode
+ */
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ rc = real_open(path, flags, PSEUDO_FS_MODE(mode));
+#else
+ rc = real_openat(dirfd, path, flags, PSEUDO_FS_MODE(mode));
+#endif
+ save_errno = errno;
+
+ if (rc != -1) {
+ int stat_rc;
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+ stat_rc = real___xstat64(_STAT_VER, path, &buf);
+#else
+ stat_rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, 0);
+#endif
+
+ if (stat_rc != -1) {
+ buf.st_mode = PSEUDO_DB_MODE(buf.st_mode, mode);
+ if (!existed) {
+ pseudo_client_op(OP_CREAT, 0, -1, dirfd, path, &buf);
+ }
+ pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, dirfd, path, &buf);
+ } else {
+ pseudo_debug(1, "openat (fd %d, path %d/%s, flags %d) succeeded, but stat failed (%s).\n",
+ rc, dirfd, path, flags, strerror(errno));
+ pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, dirfd, path, 0);
+ }
+ errno = save_errno;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/openat64.c b/ports/linux/guts/openat64.c
new file mode 100644
index 0000000..726ec6d
--- /dev/null
+++ b/ports/linux/guts/openat64.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_openat64(int dirfd, const char *path, int flags, ...mode_t mode) {
+ * int rc = -1;
+ */
+
+ rc = wrap_openat(dirfd, path, flags, mode | O_LARGEFILE);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/removexattr.c b/ports/linux/guts/removexattr.c
new file mode 100644
index 0000000..cd7f486
--- /dev/null
+++ b/ports/linux/guts/removexattr.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int removexattr(const char *pathname, const char *name)
+ * int rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) pathname;
+ (void) name;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/scandir.c b/ports/linux/guts/scandir.c
new file mode 100644
index 0000000..afcebaf
--- /dev/null
+++ b/ports/linux/guts/scandir.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_scandir(const char *path, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const void *, const void *)) {
+ * int rc = -1;
+ */
+
+ rc = real_scandir(path, namelist, filter, compar);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/scandir64.c b/ports/linux/guts/scandir64.c
new file mode 100644
index 0000000..1317b73
--- /dev/null
+++ b/ports/linux/guts/scandir64.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_scandir64(const char *path, struct dirent64 ***namelist, int (*filter)(const struct dirent64 *), int (*compar)(const void *, const void *)) {
+ * int rc = -1;
+ */
+
+ rc = real_scandir64(path, namelist, filter, compar);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/setfsgid.c b/ports/linux/guts/setfsgid.c
new file mode 100644
index 0000000..0e5a10b
--- /dev/null
+++ b/ports/linux/guts/setfsgid.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_setfsgid(gid_t fsgid) {
+ * int rc = -1;
+ */
+ if (pseudo_euid == 0 ||
+ pseudo_egid == fsgid || pseudo_rgid == fsgid || pseudo_sgid == fsgid) {
+ pseudo_fgid = fsgid;
+ rc = 0;
+ } else {
+ rc = -1;
+ errno = EPERM;
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/setfsuid.c b/ports/linux/guts/setfsuid.c
new file mode 100644
index 0000000..e52b65e
--- /dev/null
+++ b/ports/linux/guts/setfsuid.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_setfsuid(uid_t fsuid) {
+ * int rc = -1;
+ */
+ if (pseudo_euid == 0 ||
+ pseudo_euid == fsuid || pseudo_ruid == fsuid || pseudo_suid == fsuid) {
+ pseudo_fuid = fsuid;
+ rc = 0;
+ } else {
+ rc = -1;
+ errno = EPERM;
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/setgroups.c b/ports/linux/guts/setgroups.c
new file mode 100644
index 0000000..31b2b57
--- /dev/null
+++ b/ports/linux/guts/setgroups.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_setgroups(size_t size, const gid_t *list) {
+ * int rc = -1;
+ */
+
+ /* let gcc know we're ignoring these */
+ (void) size;
+ (void) list;
+ /* you always have all group privileges. we're like magic! */
+ rc = 0;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/setresgid.c b/ports/linux/guts/setresgid.c
new file mode 100644
index 0000000..2a26405
--- /dev/null
+++ b/ports/linux/guts/setresgid.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid) {
+ * int rc = -1;
+ */
+ rc = 0;
+ if (pseudo_euid != 0 && rgid != (gid_t) -1 &&
+ rgid != pseudo_egid && rgid != pseudo_rgid && rgid != pseudo_sgid) {
+ rc = -1;
+ errno = EPERM;
+ }
+ if (pseudo_euid != 0 && egid != (gid_t) -1 &&
+ egid != pseudo_egid && egid != pseudo_rgid && egid != pseudo_sgid) {
+ rc = -1;
+ errno = EPERM;
+ }
+ if (pseudo_euid != 0 && sgid != (gid_t) -1 &&
+ sgid != pseudo_egid && sgid != pseudo_rgid && sgid != pseudo_sgid) {
+ rc = -1;
+ errno = EPERM;
+ }
+ if (rc != -1) {
+ if (rgid != (gid_t) -1)
+ pseudo_rgid = rgid;
+ if (egid != (gid_t) -1)
+ pseudo_egid = egid;
+ if (sgid != (gid_t) -1)
+ pseudo_sgid = sgid;
+ pseudo_fgid = pseudo_egid;
+ pseudo_client_touchuid();
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/setresuid.c b/ports/linux/guts/setresuid.c
new file mode 100644
index 0000000..a0a367f
--- /dev/null
+++ b/ports/linux/guts/setresuid.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_setresuid(uid_t ruid, uid_t euid, uid_t suid) {
+ * int rc = -1;
+ */
+ rc = 0;
+ if (pseudo_euid != 0 && ruid != (uid_t) -1 &&
+ ruid != pseudo_euid && ruid != pseudo_ruid && ruid != pseudo_suid) {
+ rc = -1;
+ errno = EPERM;
+ }
+ if (pseudo_euid != 0 && euid != (uid_t) -1 &&
+ euid != pseudo_euid && euid != pseudo_ruid && euid != pseudo_suid) {
+ rc = -1;
+ errno = EPERM;
+ }
+ if (pseudo_euid != 0 && suid != (uid_t) -1 &&
+ suid != pseudo_euid && suid != pseudo_ruid && suid != pseudo_suid) {
+ rc = -1;
+ errno = EPERM;
+ }
+ if (rc != -1) {
+ if (ruid != (uid_t) -1)
+ pseudo_ruid = ruid;
+ if (euid != (uid_t) -1)
+ pseudo_euid = euid;
+ if (suid != (uid_t) -1)
+ pseudo_suid = suid;
+ pseudo_fuid = pseudo_euid;
+ pseudo_client_touchuid();
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/setxattr.c b/ports/linux/guts/setxattr.c
new file mode 100644
index 0000000..de2de98
--- /dev/null
+++ b/ports/linux/guts/setxattr.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int setxattr(const char *pathname, const char *name, const void *value, size_t size, int flags)
+ * int rc = -1;
+ */
+
+ /* suppress warnings */
+ (void) pathname;
+ (void) name;
+ (void) value;
+ (void) size;
+ (void) flags;
+ errno = ENOTSUP;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/stat.c b/ports/linux/guts/stat.c
new file mode 100644
index 0000000..1fe800e
--- /dev/null
+++ b/ports/linux/guts/stat.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * int stat(const char *path, struct stat *buf)
+ * int rc = -1;
+ */
+
+ rc = wrap___fxstatat(_STAT_VER, AT_FDCWD, path, buf, 0);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/truncate64.c b/ports/linux/guts/truncate64.c
new file mode 100644
index 0000000..a798984
--- /dev/null
+++ b/ports/linux/guts/truncate64.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_truncate64(const char *path, off64_t length) {
+ * int rc = -1;
+ */
+
+ rc = real_truncate64(path, length);
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/guts/ulckpwdf.c b/ports/linux/guts/ulckpwdf.c
new file mode 100644
index 0000000..bdb6f42
--- /dev/null
+++ b/ports/linux/guts/ulckpwdf.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_ulckpwdf(void) {
+ * int rc = -1;
+ */
+
+ /* lock is cleared automatically on close */
+ pseudo_pwd_lck_close();
+ rc = 0;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/linux/newclone/guts/clone.c b/ports/linux/newclone/guts/clone.c
new file mode 100644
index 0000000..b3400c7
--- /dev/null
+++ b/ports/linux/newclone/guts/clone.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * clone(...) {
+ * ....
+ */
+ /* because clone() doesn't actually continue in this function, we
+ * can't check the return and fix up environment variables in the
+ * child. Instead, we have to temporarily do any fixup, then possibly
+ * undo it later. UGH!
+ */
+ pseudo_debug(1, "client resetting for clone(2) call\n");
+ if (!pseudo_get_value("PSEUDO_RELOADED")) {
+ pseudo_setupenv();
+ pseudo_reinit_libpseudo();
+ } else {
+ pseudo_setupenv();
+ pseudo_dropenv();
+ }
+ /* call the real syscall */
+ rc = (*real_clone)(fn, child_stack, flags, arg, pid, tls, ctid);
+/* ...
+ * return rc;
+ * }
+ */
diff --git a/ports/linux/newclone/pseudo_wrappers.c b/ports/linux/newclone/pseudo_wrappers.c
new file mode 100644
index 0000000..dd44408
--- /dev/null
+++ b/ports/linux/newclone/pseudo_wrappers.c
@@ -0,0 +1,69 @@
+static int
+wrap_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, va_list
+ap) {
+ /* unused */
+ (void) fn;
+ (void) child_stack;
+ (void) flags;
+ (void) arg;
+ (void) ap;
+ return 0;
+}
+
+int
+clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) {
+ sigset_t saved;
+ va_list ap;
+ pid_t *pid;
+ struct user_desc *tls;
+ pid_t *ctid;
+
+ int rc = -1;
+
+ if (!pseudo_check_wrappers() || !real_clone) {
+ /* rc was initialized to the "failure" value */
+ pseudo_enosys("clone");
+ return rc;
+ }
+
+ va_start(ap, arg);
+ pid = va_arg(ap, pid_t *);
+ tls = va_arg(ap, struct user_desc *);
+ ctid = va_arg(ap, pid_t *);
+ va_end(ap);
+
+ pseudo_debug(4, "called: clone\n");
+ pseudo_sigblock(&saved);
+ if (pseudo_getlock()) {
+ errno = EBUSY;
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ return -1;
+ }
+
+ int save_errno;
+ int save_disabled = pseudo_disabled;
+ /* because clone() doesn't actually continue in this function, we
+ * can't check the return and fix up environment variables in the
+ * child. Instead, we have to temporarily do any fixup, then possibly
+ * undo it later. UGH!
+ */
+
+#include "guts/clone.c"
+
+ if (save_disabled != pseudo_disabled) {
+ if (pseudo_disabled) {
+ pseudo_disabled = 0;
+ pseudo_magic();
+ } else {
+ pseudo_disabled = 1;
+ pseudo_antimagic();
+ }
+ }
+
+ save_errno = errno;
+ pseudo_droplock();
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ pseudo_debug(4, "completed: clone\n");
+ errno = save_errno;
+ return rc;
+}
diff --git a/ports/linux/newclone/wrapfuncs.in b/ports/linux/newclone/wrapfuncs.in
new file mode 100644
index 0000000..8849310
--- /dev/null
+++ b/ports/linux/newclone/wrapfuncs.in
@@ -0,0 +1 @@
+int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...); /* hand_wrapped=1 */
diff --git a/ports/linux/oldclone/guts/clone.c b/ports/linux/oldclone/guts/clone.c
new file mode 100644
index 0000000..58ff4ad
--- /dev/null
+++ b/ports/linux/oldclone/guts/clone.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * clone(...) {
+ * ....
+ */
+ /* because clone() doesn't actually continue in this function, we
+ * can't check the return and fix up environment variables in the
+ * child. Instead, we have to temporarily do any fixup, then possibly
+ * undo it later. UGH!
+ */
+ pseudo_debug(1, "client resetting for clone(2) call\n");
+ if (!pseudo_get_value("PSEUDO_RELOADED")) {
+ pseudo_setupenv();
+ pseudo_reinit_libpseudo();
+ } else {
+ pseudo_setupenv();
+ pseudo_dropenv();
+ }
+ /* call the real syscall */
+ rc = (*real_clone)(fn, child_stack, flags, arg);
+/* ...
+ * return rc;
+ * }
+ */
diff --git a/ports/linux/oldclone/pseudo_wrappers.c b/ports/linux/oldclone/pseudo_wrappers.c
new file mode 100644
index 0000000..dead493
--- /dev/null
+++ b/ports/linux/oldclone/pseudo_wrappers.c
@@ -0,0 +1,59 @@
+static int (*real_clone)(int (*)(void *), void *, int, void *) = NULL;
+
+int
+wrap_clone(int (*fn)(void *), void *child_stack, int flags, void *arg) {
+ /* unused */
+ return 0;
+}
+
+int
+clone(int (*fn)(void *), void *child_stack, int flags, void *arg) {
+ sigset_t saved;
+ va_list ap;
+ pid_t *pid;
+ struct user_desc *tls;
+ pid_t *ctid;
+
+ int rc = -1;
+
+ if (!pseudo_check_wrappers() || !real_clone) {
+ /* rc was initialized to the "failure" value */
+ pseudo_enosys("clone");
+ return rc;
+ }
+
+ pseudo_debug(4, "called: clone\n");
+ pseudo_sigblock(&saved);
+ if (pseudo_getlock()) {
+ errno = EBUSY;
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ return -1;
+ }
+
+ int save_errno;
+ int save_disabled = pseudo_disabled;
+ /* because clone() doesn't actually continue in this function, we
+ * can't check the return and fix up environment variables in the
+ * child. Instead, we have to temporarily do any fixup, then possibly
+ * undo it later. UGH!
+ */
+
+#include "guts/clone.c"
+
+ if (save_disabled != pseudo_disabled) {
+ if (pseudo_disabled) {
+ pseudo_disabled = 0;
+ pseudo_magic();
+ } else {
+ pseudo_disabled = 1;
+ pseudo_antimagic();
+ }
+ }
+
+ save_errno = errno;
+ pseudo_droplock();
+ sigprocmask(SIG_SETMASK, &saved, NULL);
+ pseudo_debug(4, "completed: clone\n");
+ errno = save_errno;
+ return rc;
+}
diff --git a/ports/linux/oldclone/wrapfuncs.in b/ports/linux/oldclone/wrapfuncs.in
new file mode 100644
index 0000000..c915376
--- /dev/null
+++ b/ports/linux/oldclone/wrapfuncs.in
@@ -0,0 +1 @@
+int clone(int (*fn)(void *), void *child_stack, int flags, void *arg); /* hand_wrapped=1 */
diff --git a/ports/linux/portdefs.h b/ports/linux/portdefs.h
new file mode 100644
index 0000000..7e6c2aa
--- /dev/null
+++ b/ports/linux/portdefs.h
@@ -0,0 +1,5 @@
+#define PRELINK_LIBRARIES "LD_PRELOAD"
+#define PRELINK_PATH "LD_LIBRARY_PATH"
+#define PSEUDO_STATBUF_64 1
+#define PSEUDO_STATBUF struct stat64
+#define PSEUDO_LINKPATH_SEPARATOR " "
diff --git a/ports/linux/preports b/ports/linux/preports
new file mode 100644
index 0000000..a996c69
--- /dev/null
+++ b/ports/linux/preports
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo "unix" "uids_generic"
diff --git a/ports/linux/pseudo_wrappers.c b/ports/linux/pseudo_wrappers.c
new file mode 100644
index 0000000..7d3fcd5
--- /dev/null
+++ b/ports/linux/pseudo_wrappers.c
@@ -0,0 +1,18 @@
+
+/* the unix port wants to know that real_stat() and
+ * friends exist. So they do.
+ */
+int
+pseudo_stat(const char *path, struct stat *buf) {
+ return real___xstat(_STAT_VER, path, buf);
+}
+
+int
+pseudo_lstat(const char *path, struct stat *buf) {
+ return real___lxstat(_STAT_VER, path, buf);
+}
+
+int
+pseudo_fstat(int fd, struct stat *buf) {
+ return real___fxstat(_STAT_VER, fd, buf);
+}
diff --git a/ports/linux/subports b/ports/linux/subports
new file mode 100644
index 0000000..02a4688
--- /dev/null
+++ b/ports/linux/subports
@@ -0,0 +1,27 @@
+#!/bin/sh
+found=false
+printf >&2 "Checking for old/new clone mechanics..."
+cat > dummy.c <<EOF
+#include <sched.h>
+int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) { return 0; }
+EOF
+if cc -c -o dummy.o dummy.c >/dev/null 2>&1; then
+ rm -f dummy.c dummy.o
+ echo >&2 "New clone."
+ echo "linux/newclone"
+ found=true
+fi
+cat > dummy.c <<EOF
+#include <sched.h>
+int clone(int (*fn)(void *), void *child_stack, int flags, void *arg) { return 0; }
+EOF
+if ! $found && cc -c -o dummy.o dummy.c >/dev/null 2>&1; then
+ rm -f dummy.c dummy.o
+ echo >&2 "Old clone."
+ echo "linux/oldclone"
+ found=true
+fi
+rm -f dummy.c dummy.o
+if ! $found; then
+ echo >&2 "Can't tell, omitting clone(2) support."
+fi
diff --git a/ports/linux/wrapfuncs.in b/ports/linux/wrapfuncs.in
new file mode 100644
index 0000000..2dab39d
--- /dev/null
+++ b/ports/linux/wrapfuncs.in
@@ -0,0 +1,64 @@
+int open(const char *path, int flags, ...{mode_t mode}); /* flags=0 */
+char *get_current_dir_name(void);
+int __xstat(int ver, const char *path, struct stat *buf);
+int __lxstat(int ver, const char *path, struct stat *buf); /* flags=AT_SYMLINK_NOFOLLOW */
+int __fxstat(int ver, int fd, struct stat *buf);
+int lchown(const char *path, uid_t owner, gid_t group); /* flags=AT_SYMLINK_NOFOLLOW */
+int __fxstatat(int ver, int dirfd, const char *path, struct stat *buf, int flags);
+int openat(int dirfd, const char *path, int flags, ...{mode_t mode});
+int __openat_2(int dirfd, const char *path, int flags);
+int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev); /* flags=AT_SYMLINK_NOFOLLOW */
+int __xmknodat(int ver, int dirfd, const char *path, mode_t mode, dev_t *dev); /* flags=AT_SYMLINK_NOFOLLOW */
+int fcntl(int fd, int cmd, ...{struct flock *lock});
+# just so we know the inums of symlinks
+char *canonicalize_file_name(const char *filename);
+int eaccess(const char *path, int mode);
+# we use "pathname" to avoid canonicalizing paths, because these functions are
+# unimplemented
+ssize_t getxattr(const char *pathname, const char *name, void *value, size_t size);
+ssize_t lgetxattr(const char *pathname, const char *name, void *value, size_t size);
+ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size);
+ssize_t listxattr(const char *pathname, char *list, size_t size);
+ssize_t llistxattr(const char *pathname, char *list, size_t size);
+ssize_t flistxattr(int filedes, char *list, size_t size);
+int setxattr(const char *pathname, const char *name, const void *value, size_t size, int flags);
+int lsetxattr(const char *pathname, const char *name, const void *value, size_t size, int flags);
+int fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags);
+int removexattr(const char *pathname, const char *name);
+int lremovexattr(const char *pathname, const char *name);
+int fremovexattr(int filedes, const char *name);
+int open64(const char *path, int flags, ...{mode_t mode}); /* flags=0 */
+int openat64(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=0 */
+int __openat64_2(int dirfd, const char *path, int flags); /* flags=0 */
+int creat64(const char *path, mode_t mode);
+int stat(const char *path, struct stat *buf); /* real_func=pseudo_stat */
+int lstat(const char *path, struct stat *buf); /* real_func=pseudo_lstat */
+int fstat(int fd, struct stat *buf); /* real_func=pseudo_fstat */
+int __xstat64(int ver, const char *path, struct stat64 *buf);
+int __lxstat64(int ver, const char *path, struct stat64 *buf); /* flags=AT_SYMLINK_NOFOLLOW */
+int __fxstat64(int ver, int fd, struct stat64 *buf);
+int __fxstatat64(int ver, int dirfd, const char *path, struct stat64 *buf, int flags);
+FILE *fopen64(const char *path, const char *mode);
+int nftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int, struct FTW *), int nopenfd, int flag);
+FILE *freopen64(const char *path, const char *mode, FILE *stream);
+int ftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int), int nopenfd);
+int glob64(const char *pattern, int flags, int (*errfunc)(const char *, int), glob64_t *pglob);
+int scandir64(const char *path, struct dirent64 ***namelist, int (*filter)(const struct dirent64 *), int (*compar)());
+int truncate64(const char *path, off64_t length);
+int mkstemp64(char *template); /* flags=AT_SYMLINK_NOFOLLOW */
+int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups);
+int setgroups(size_t size, const gid_t *list);
+int setfsgid(gid_t fsgid);
+int setfsuid(uid_t fsuid);
+int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
+int setresuid(uid_t ruid, uid_t euid, uid_t suid);
+int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
+int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
+int scandir(const char *path, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)());
+int getgroups(int size, gid_t *list);
+int lckpwdf(void);
+int ulckpwdf(void);
+int euidaccess(const char *path, int mode);
+int getpw(uid_t uid, char *buf);
+int getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
+int getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp);
diff --git a/ports/uids_generic/guts/COPYRIGHT b/ports/uids_generic/guts/COPYRIGHT
new file mode 100644
index 0000000..c96e1b1
--- /dev/null
+++ b/ports/uids_generic/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/uids_generic/guts/endgrent.c b/ports/uids_generic/guts/endgrent.c
new file mode 100644
index 0000000..843cad0
--- /dev/null
+++ b/ports/uids_generic/guts/endgrent.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static void
+ * wrap_endgrent(void) {
+ *
+ */
+
+ pseudo_grp_close();
+
+/* return;
+ * }
+ */
diff --git a/ports/uids_generic/guts/endpwent.c b/ports/uids_generic/guts/endpwent.c
new file mode 100644
index 0000000..f76cf10
--- /dev/null
+++ b/ports/uids_generic/guts/endpwent.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static void
+ * wrap_endpwent(void) {
+ *
+ */
+
+ pseudo_pwd_close();
+
+/* return;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getegid.c b/ports/uids_generic/guts/getegid.c
new file mode 100644
index 0000000..7c14f48
--- /dev/null
+++ b/ports/uids_generic/guts/getegid.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static gid_t
+ * wrap_getegid(void) {
+ * gid_t rc = 0;
+ */
+
+ rc = pseudo_egid;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/geteuid.c b/ports/uids_generic/guts/geteuid.c
new file mode 100644
index 0000000..1745e13
--- /dev/null
+++ b/ports/uids_generic/guts/geteuid.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static uid_t
+ * wrap_geteuid(void) {
+ * uid_t rc = 0;
+ */
+
+ rc = pseudo_euid;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getgid.c b/ports/uids_generic/guts/getgid.c
new file mode 100644
index 0000000..ca8bad3
--- /dev/null
+++ b/ports/uids_generic/guts/getgid.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static gid_t
+ * wrap_getgid(void) {
+ * gid_t rc = 0;
+ */
+
+ rc = pseudo_rgid;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getgrent.c b/ports/uids_generic/guts/getgrent.c
new file mode 100644
index 0000000..e8e07f5
--- /dev/null
+++ b/ports/uids_generic/guts/getgrent.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static struct group *
+ * wrap_getgrent(void) {
+ * struct group * rc = NULL;
+ */
+ static struct group grp;
+ static char grbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getgrent_r(&grp, grbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getgrgid.c b/ports/uids_generic/guts/getgrgid.c
new file mode 100644
index 0000000..c1824e7
--- /dev/null
+++ b/ports/uids_generic/guts/getgrgid.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static struct group *
+ * wrap_getgrgid(gid_t gid) {
+ * struct group * rc = NULL;
+ */
+ static struct group grp;
+ static char grbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getgrgid_r(gid, &grp, grbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getgrgid_r.c b/ports/uids_generic/guts/getgrgid_r.c
new file mode 100644
index 0000000..06a91c9
--- /dev/null
+++ b/ports/uids_generic/guts/getgrgid_r.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getgrgid_r(gid_t gid, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
+ * int rc = -1;
+ */
+
+ setgrent();
+ while ((rc = wrap_getgrent_r(gbuf, buf, buflen, gbufp)) == 0) {
+ /* 0 means no error occurred, and *gbufp == gbuf */
+ if (gbuf->gr_gid == gid) {
+ pseudo_debug(1, "found group gid %d, name %s\n",
+ gbuf->gr_gid, gbuf->gr_name);
+ endgrent();
+ return rc;
+ }
+ }
+ endgrent();
+ /* we never found a match; rc is 0 if there was no error, or
+ * non-zero if an error occurred. Either way, set the
+ * pwbufp pointer to NULL to indicate that we didn't find
+ * something, and leave rc alone.
+ */
+ *gbufp = NULL;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getgrnam.c b/ports/uids_generic/guts/getgrnam.c
new file mode 100644
index 0000000..0e26444
--- /dev/null
+++ b/ports/uids_generic/guts/getgrnam.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static struct group *
+ * wrap_getgrnam(const char *name) {
+ * struct group * rc = NULL;
+ */
+
+ static struct group grp;
+ static char grbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getgrnam_r(name, &grp, grbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getgrnam_r.c b/ports/uids_generic/guts/getgrnam_r.c
new file mode 100644
index 0000000..39de641
--- /dev/null
+++ b/ports/uids_generic/guts/getgrnam_r.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getgrnam_r(const char *name, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
+ * int rc = -1;
+ */
+
+ setgrent();
+ while ((rc = wrap_getgrent_r(gbuf, buf, buflen, gbufp)) == 0) {
+ /* 0 means no error occurred, and *gbufp == gbuf */
+ if (gbuf->gr_name && !strcmp(gbuf->gr_name, name)) {
+ endgrent();
+ return rc;
+ }
+ }
+ endgrent();
+ /* we never found a match; rc is 0 if there was no error, or
+ * non-zero if an error occurred. Either way, set the
+ * pwbufp pointer to NULL to indicate that we didn't find
+ * something, and leave rc alone.
+ */
+ *gbufp = NULL;
+
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getpwent.c b/ports/uids_generic/guts/getpwent.c
new file mode 100644
index 0000000..3b1f837
--- /dev/null
+++ b/ports/uids_generic/guts/getpwent.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static struct passwd *
+ * wrap_getpwent(void) {
+ * struct passwd * rc = NULL;
+ */
+ static struct passwd pwd;
+ static char pwbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getpwent_r(&pwd, pwbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getpwnam.c b/ports/uids_generic/guts/getpwnam.c
new file mode 100644
index 0000000..024b3d8
--- /dev/null
+++ b/ports/uids_generic/guts/getpwnam.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static struct passwd *
+ * wrap_getpwnam(const char *name) {
+ * struct passwd * rc = NULL;
+ */
+ static struct passwd pwd;
+ static char pwbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getpwnam_r(name, &pwd, pwbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getpwnam_r.c b/ports/uids_generic/guts/getpwnam_r.c
new file mode 100644
index 0000000..5d7a4ea
--- /dev/null
+++ b/ports/uids_generic/guts/getpwnam_r.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) {
+ * int rc = -1;
+ */
+
+ setpwent();
+ while ((rc = wrap_getpwent_r(pwbuf, buf, buflen, pwbufp)) == 0) {
+ /* 0 means no error occurred, and *pwbufp == pwbuf */
+ if (pwbuf->pw_name && !strcmp(pwbuf->pw_name, name)) {
+ endpwent();
+ return rc;
+ }
+ }
+ endpwent();
+ /* we never found a match; rc is 0 if there was no error, or
+ * non-zero if an error occurred. Either way, set the
+ * pwbufp pointer to NULL to indicate that we didn't find
+ * something, and leave rc alone.
+ */
+ *pwbufp = NULL;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getpwuid.c b/ports/uids_generic/guts/getpwuid.c
new file mode 100644
index 0000000..11142de
--- /dev/null
+++ b/ports/uids_generic/guts/getpwuid.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static struct passwd *
+ * wrap_getpwuid(uid_t uid) {
+ * struct passwd * rc = NULL;
+ */
+ static struct passwd pwd;
+ static char pwbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getpwuid_r(uid, &pwd, pwbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getpwuid_r.c b/ports/uids_generic/guts/getpwuid_r.c
new file mode 100644
index 0000000..06b920e
--- /dev/null
+++ b/ports/uids_generic/guts/getpwuid_r.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_getpwuid_r(uid_t uid, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) {
+ * int rc = -1;
+ */
+
+ setpwent();
+ while ((rc = wrap_getpwent_r(pwbuf, buf, buflen, pwbufp)) == 0) {
+ /* 0 means no error occurred, and *pwbufp == pwbuf */
+ if (pwbuf->pw_uid == uid) {
+ endpwent();
+ return rc;
+ }
+ }
+ endpwent();
+ /* we never found a match; rc is 0 if there was no error, or
+ * non-zero if an error occurred. Either way, set the
+ * pwbufp pointer to NULL to indicate that we didn't find
+ * something, and leave rc alone.
+ */
+ *pwbufp = NULL;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/getuid.c b/ports/uids_generic/guts/getuid.c
new file mode 100644
index 0000000..e783cc8
--- /dev/null
+++ b/ports/uids_generic/guts/getuid.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static uid_t
+ * wrap_getuid(void) {
+ * uid_t rc = 0;
+ */
+
+ rc = pseudo_ruid;
+
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/setegid.c b/ports/uids_generic/guts/setegid.c
new file mode 100644
index 0000000..ff777a0
--- /dev/null
+++ b/ports/uids_generic/guts/setegid.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_setegid(gid_t egid) {
+ * int rc = -1;
+ */
+ if (pseudo_euid == 0 || egid == pseudo_egid || egid == pseudo_rgid || egid == pseudo_sgid) {
+ pseudo_egid = egid;
+ pseudo_fgid = egid;
+ pseudo_client_touchgid();
+ rc = 0;
+ } else {
+ rc = -1;
+ errno = EPERM;
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/seteuid.c b/ports/uids_generic/guts/seteuid.c
new file mode 100644
index 0000000..430768f
--- /dev/null
+++ b/ports/uids_generic/guts/seteuid.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_seteuid(uid_t euid) {
+ * int rc = -1;
+ */
+ if (pseudo_euid == 0 || euid == pseudo_euid || euid == pseudo_ruid || euid == pseudo_suid) {
+ pseudo_euid = euid;
+ pseudo_fuid = euid;
+ pseudo_client_touchuid();
+ rc = 0;
+ } else {
+ rc = -1;
+ errno = EPERM;
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/setgid.c b/ports/uids_generic/guts/setgid.c
new file mode 100644
index 0000000..b94db1a
--- /dev/null
+++ b/ports/uids_generic/guts/setgid.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_setgid(gid_t gid) {
+ * int rc = -1;
+ */
+ if (pseudo_euid == 0) {
+ pseudo_rgid = gid;
+ pseudo_egid = gid;
+ pseudo_sgid = gid;
+ pseudo_fgid = gid;
+ pseudo_client_touchgid();
+ rc = 0;
+ } else if (pseudo_egid == gid || pseudo_sgid == gid || pseudo_rgid == gid) {
+ pseudo_egid = gid;
+ pseudo_fgid = gid;
+ pseudo_client_touchgid();
+ rc = 0;
+ } else {
+ rc = -1;
+ errno = EPERM;
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/setgrent.c b/ports/uids_generic/guts/setgrent.c
new file mode 100644
index 0000000..75aab61
--- /dev/null
+++ b/ports/uids_generic/guts/setgrent.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static void
+ * wrap_setgrent(void) {
+ *
+ */
+
+ pseudo_grp_open();
+
+/* return;
+ * }
+ */
diff --git a/ports/uids_generic/guts/setpwent.c b/ports/uids_generic/guts/setpwent.c
new file mode 100644
index 0000000..fb35e07
--- /dev/null
+++ b/ports/uids_generic/guts/setpwent.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static void
+ * wrap_setpwent(void) {
+ *
+ */
+
+ pseudo_pwd_open();
+
+/* return;
+ * }
+ */
diff --git a/ports/uids_generic/guts/setregid.c b/ports/uids_generic/guts/setregid.c
new file mode 100644
index 0000000..78b2037
--- /dev/null
+++ b/ports/uids_generic/guts/setregid.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_setregid(gid_t rgid, gid_t egid) {
+ * int rc = -1;
+ */
+ rc = 0;
+ if (pseudo_euid != 0 && rgid != (gid_t) -1 &&
+ rgid != pseudo_egid && rgid != pseudo_rgid && rgid != pseudo_sgid) {
+ rc = -1;
+ errno = EPERM;
+ }
+ if (pseudo_euid != 0 && egid != (gid_t) -1 &&
+ egid != pseudo_egid && egid != pseudo_rgid && egid != pseudo_sgid) {
+ rc = -1;
+ errno = EPERM;
+ }
+ if (rc != -1) {
+ if (rgid != (gid_t) -1)
+ pseudo_rgid = rgid;
+ if (egid != (gid_t) -1)
+ pseudo_egid = egid;
+ pseudo_fgid = pseudo_egid;
+ pseudo_client_touchuid();
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/setreuid.c b/ports/uids_generic/guts/setreuid.c
new file mode 100644
index 0000000..3ff82ab
--- /dev/null
+++ b/ports/uids_generic/guts/setreuid.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_setreuid(uid_t ruid, uid_t euid) {
+ * int rc = -1;
+ */
+ rc = 0;
+ if (pseudo_euid != 0 && ruid != (uid_t) -1 &&
+ ruid != pseudo_euid && ruid != pseudo_ruid && ruid != pseudo_suid) {
+ rc = -1;
+ errno = EPERM;
+ }
+ if (pseudo_euid != 0 && euid != (uid_t) -1 &&
+ euid != pseudo_euid && euid != pseudo_ruid && euid != pseudo_suid) {
+ rc = -1;
+ errno = EPERM;
+ }
+ if (rc != -1) {
+ if (ruid != (uid_t) -1)
+ pseudo_ruid = ruid;
+ if (euid != (uid_t) -1)
+ pseudo_euid = euid;
+ pseudo_fuid = pseudo_euid;
+ pseudo_client_touchuid();
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/guts/setuid.c b/ports/uids_generic/guts/setuid.c
new file mode 100644
index 0000000..6bfdf6c
--- /dev/null
+++ b/ports/uids_generic/guts/setuid.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2008-2010 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * static int
+ * wrap_setuid(uid_t uid) {
+ * int rc = -1;
+ */
+ if (pseudo_euid == 0) {
+ pseudo_ruid = uid;
+ pseudo_euid = uid;
+ pseudo_suid = uid;
+ pseudo_fuid = uid;
+ pseudo_client_touchuid();
+ rc = 0;
+ } else if (pseudo_euid == uid || pseudo_suid == uid || pseudo_ruid == uid) {
+ pseudo_euid = uid;
+ pseudo_fuid = uid;
+ pseudo_client_touchuid();
+ rc = 0;
+ } else {
+ rc = -1;
+ errno = EPERM;
+ }
+/* return rc;
+ * }
+ */
diff --git a/ports/uids_generic/wrapfuncs.in b/ports/uids_generic/wrapfuncs.in
new file mode 100644
index 0000000..38aa558
--- /dev/null
+++ b/ports/uids_generic/wrapfuncs.in
@@ -0,0 +1,25 @@
+# I bet you never knew there were this many of these!
+gid_t getegid(void);
+gid_t getgid(void);
+int getgrgid_r(gid_t gid, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp);
+int getgrnam_r(const char *name, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp);
+int getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
+int getpwuid_r(uid_t uid, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
+int setegid(gid_t egid);
+int seteuid(uid_t euid);
+int setgid(gid_t gid);
+int setregid(gid_t rgid, gid_t egid);
+int setreuid(uid_t ruid, uid_t euid);
+int setuid(uid_t uid);
+struct group *getgrent(void);
+struct group *getgrgid(gid_t gid);
+struct group *getgrnam(const char *name);
+struct passwd *getpwent(void);
+struct passwd *getpwnam(const char *name);
+struct passwd *getpwuid(uid_t uid);
+uid_t geteuid(void);
+uid_t getuid(void);
+void endgrent(void);
+void endpwent(void);
+void setgrent(void);
+void setpwent(void);
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 */