---  include/stdio.h.orig
+++  include/stdio.h
@@ -447,5 +447,6 @@
 #define	putchar_unlocked(x)	putc_unlocked(x, stdout)
 #endif
 
+int	 renameat(int, const char *, int, const char *);
 __END_DECLS
 #endif /* !_STDIO_H_ */
---  include/unistd.h.orig
+++  include/unistd.h
@@ -558,6 +558,15 @@
 extern int optreset;			/* getopt(3) external variable */
 #endif
 #endif /* __BSD_VISIBLE */
+
+int	faccessat(int, const char *, int);
+int	fchmodat(int, const char *, mode_t, int);
+int	fchownat(int, const char *, uid_t, gid_t, int);
+int	fexecve(int, char *const [], char *const []);
+int	linkat(int, const char *, int, const char *, int);
+ssize_t	readlinkat(int, const char *, char *, size_t);
+int	symlinkat(const char *, int, const char *);
+int	unlinkat(int, const char *, int);
 __END_DECLS
 
 #endif /* !_UNISTD_H_ */
---  lib/libc/gen/Makefile.inc.orig
+++  lib/libc/gen/Makefile.inc
@@ -10,7 +10,7 @@
 	clock.c closedir.c confstr.c \
 	crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
 	dlfcn.c dlfunc.c drand48.c erand48.c err.c errlst.c errno.c \
-	exec.c fmtcheck.c fmtmsg.c fnmatch.c \
+	exec.c fdopendir.c fmtcheck.c fmtmsg.c fnmatch.c \
 	fpclassify.c frexp.c fstab.c ftok.c fts.c ftw.c \
 	getbootfile.c getbsize.c \
 	getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \
---  lib/libc/gen/Symbol.map.orig
+++  lib/libc/gen/Symbol.map
@@ -227,6 +227,7 @@
 	nlist;
 	nrand48;
 	opendir;
+	fdopendir;
 	pause;
 	posix_madvise;
 	popen;
---  lib/libc/sys/Symbol.map.orig
+++  lib/libc/sys/Symbol.map
@@ -963,4 +963,19 @@
 	_writev;
 	__sys_writev;
 	__error_unthreaded;
+	faccessat;
+	fchmodat;
+	fchownat;
+	fexecve;
+	fstatat;
+	futimesat;
+	linkat;
+	mkdirat;
+	mkfifoat;
+	mknodat;
+	openat;
+	readlinkat;
+	renameat;
+	symlinkat;
+	unlinkat;
 };
--- /dev/null	2007-12-28 15:55:00.000000000 +0100
+++ lib/libc/gen/fdopendir.c	2007-12-28 15:55:10.000000000 +0100
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)opendir.c	8.8 (Berkeley) 5/1/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "telldir.h"
+/*
+ * Open a directory.
+ */
+DIR *
+fdopendir(fd)
+	const int fd;
+{
+
+	return (__fdopendir2(fd, DTF_HIDEW|DTF_NODUP));
+}
+
+DIR *
+__fdopendir2(fd, flags)
+	const int fd;
+	int flags;
+{
+	DIR *dirp;
+	int incr;
+	int saved_errno;
+	int unionstack;
+	struct stat statb;
+
+	dirp = NULL;
+	if (_fstat(fd, &statb) != 0)
+		goto fail;
+	if (!S_ISDIR(statb.st_mode)) {
+		errno = ENOTDIR;
+		goto fail;
+	}
+	if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 ||
+	    (dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL)
+		goto fail;
+
+	dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR));
+	LIST_INIT(&dirp->dd_td->td_locq);
+	dirp->dd_td->td_loccnt = 0;
+
+	/*
+	 * Use the system page size if that is a multiple of DIRBLKSIZ.
+	 * Hopefully this can be a big win someday by allowing page
+	 * trades to user space to be done by _getdirentries().
+	 */
+	incr = getpagesize();
+	if ((incr % DIRBLKSIZ) != 0) 
+		incr = DIRBLKSIZ;
+
+	/*
+	 * Determine whether this directory is the top of a union stack.
+	 */
+	if (flags & DTF_NODUP) {
+		struct statfs sfb;
+
+		if (_fstatfs(fd, &sfb) < 0)
+			goto fail;
+		unionstack = !strcmp(sfb.f_fstypename, "unionfs")
+		    || (sfb.f_flags & MNT_UNION);
+	} else {
+		unionstack = 0;
+	}
+
+	if (unionstack) {
+		int len = 0;
+		int space = 0;
+		char *buf = 0;
+		char *ddptr = 0;
+		char *ddeptr;
+		int n;
+		struct dirent **dpv;
+
+		/*
+		 * The strategy here is to read all the directory
+		 * entries into a buffer, sort the buffer, and
+		 * remove duplicate entries by setting the inode
+		 * number to zero.
+		 */
+
+		do {
+			/*
+			 * Always make at least DIRBLKSIZ bytes
+			 * available to _getdirentries
+			 */
+			if (space < DIRBLKSIZ) {
+				space += incr;
+				len += incr;
+				buf = reallocf(buf, len);
+				if (buf == NULL)
+					goto fail;
+				ddptr = buf + (len - space);
+			}
+
+			n = _getdirentries(fd, ddptr, space, &dirp->dd_seek);
+			if (n > 0) {
+				ddptr += n;
+				space -= n;
+			}
+		} while (n > 0);
+
+		ddeptr = ddptr;
+		flags |= __DTF_READALL;
+
+		/*
+		 * Re-open the directory.
+		 * This has the effect of rewinding back to the
+		 * top of the union stack and is needed by
+		 * programs which plan to fchdir to a descriptor
+		 * which has also been read -- see fts.c.
+		 */
+		if (flags & DTF_REWIND) {
+		/* XXX: what here? */
+		}
+
+		/*
+		 * There is now a buffer full of (possibly) duplicate
+		 * names.
+		 */
+		dirp->dd_buf = buf;
+
+		/*
+		 * Go round this loop twice...
+		 *
+		 * Scan through the buffer, counting entries.
+		 * On the second pass, save pointers to each one.
+		 * Then sort the pointers and remove duplicate names.
+		 */
+		for (dpv = 0;;) {
+			n = 0;
+			ddptr = buf;
+			while (ddptr < ddeptr) {
+				struct dirent *dp;
+
+				dp = (struct dirent *) ddptr;
+				if ((long)dp & 03L)
+					break;
+				if ((dp->d_reclen <= 0) ||
+				    (dp->d_reclen > (ddeptr + 1 - ddptr)))
+					break;
+				ddptr += dp->d_reclen;
+				if (dp->d_fileno) {
+					if (dpv)
+						dpv[n] = dp;
+					n++;
+				}
+			}
+
+			if (dpv) {
+				struct dirent *xp;
+
+				/*
+				 * This sort must be stable.
+				 */
+				mergesort(dpv, n, sizeof(*dpv), alphasort);
+
+				dpv[n] = NULL;
+				xp = NULL;
+
+				/*
+				 * Scan through the buffer in sort order,
+				 * zapping the inode number of any
+				 * duplicate names.
+				 */
+				for (n = 0; dpv[n]; n++) {
+					struct dirent *dp = dpv[n];
+
+					if ((xp == NULL) ||
+					    strcmp(dp->d_name, xp->d_name)) {
+						xp = dp;
+					} else {
+						dp->d_fileno = 0;
+					}
+					if (dp->d_type == DT_WHT &&
+					    (flags & DTF_HIDEW))
+						dp->d_fileno = 0;
+				}
+
+				free(dpv);
+				break;
+			} else {
+				dpv = malloc((n+1) * sizeof(struct dirent *));
+				if (dpv == NULL)
+					break;
+			}
+		}
+
+		dirp->dd_len = len;
+		dirp->dd_size = ddptr - dirp->dd_buf;
+	} else {
+		dirp->dd_len = incr;
+		dirp->dd_size = 0;
+		dirp->dd_buf = malloc(dirp->dd_len);
+		if (dirp->dd_buf == NULL)
+			goto fail;
+		dirp->dd_seek = 0;
+		flags &= ~DTF_REWIND;
+	}
+
+	dirp->dd_loc = 0;
+	dirp->dd_fd = fd;
+	dirp->dd_flags = flags;
+	dirp->dd_lock = NULL;
+
+	/*
+	 * Set up seek point for rewinddir.
+	 */
+	dirp->dd_rewind = telldir(dirp);
+
+	return (dirp);
+
+fail:
+	saved_errno = errno;
+	free(dirp);
+	errno = saved_errno;
+	return (NULL);
+}
---  include/dirent.h.orig
+++  include/dirent.h
@@ -95,11 +95,13 @@
 __BEGIN_DECLS
 #if __BSD_VISIBLE
 DIR	*__opendir2(const char *, int);
+DIR	*__fdopendir2(int, int);
 int	 alphasort(const void *, const void *);
 int	 getdents(int, char *, int);
 int	 getdirentries(int, char *, int, long *);
 #endif
 DIR	*opendir(const char *);
+DIR	*fdopendir(int);
 struct dirent *
 	 readdir(DIR *);
 #if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE >= 500
