aboutsummaryrefslogtreecommitdiffstats
path: root/ports
diff options
context:
space:
mode:
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 */