---  amd64/linux32/linux.h.orig
+++  amd64/linux32/linux.h
@@ -566,8 +566,6 @@
 #define	LINUX_F_WRLCK		1
 #define	LINUX_F_UNLCK		2
 
-#define	LINUX_AT_FDCWD		-100
-
 /*
  * mount flags
  */
---  amd64/linux32/linux32_dummy.c.orig
+++  amd64/linux32/linux32_dummy.c
@@ -96,18 +96,6 @@
 DUMMY(inotify_add_watch);
 DUMMY(inotify_rm_watch);
 DUMMY(migrate_pages);
-DUMMY(mkdirat);
-DUMMY(mknodat);
-DUMMY(fchownat);
-DUMMY(futimesat);
-DUMMY(fstatat64);
-DUMMY(unlinkat);
-DUMMY(renameat);
-DUMMY(linkat);
-DUMMY(symlinkat);
-DUMMY(readlinkat);
-DUMMY(fchmodat);
-DUMMY(faccessat);
 DUMMY(pselect6);
 DUMMY(ppoll);
 DUMMY(unshare);
---  amd64/linux32/linux32_proto.h.orig
+++  amd64/linux32/linux32_proto.h
@@ -2,7 +2,7 @@
  * System call prototypes.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/amd64/linux32/linux32_proto.h,v 1.31 2007/03/30 00:08:21 jkim Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.28 2007/03/30 00:06:21 jkim Exp 
  */
 
@@ -880,40 +880,72 @@
 	char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)];
 };
 struct linux_mkdirat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char pathname_l_[PADL_(char *)]; char * pathname; char pathname_r_[PADR_(char *)];
+	char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)];
 };
 struct linux_mknodat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)];
+	char dev_l_[PADL_(l_uint)]; l_uint dev; char dev_r_[PADR_(l_uint)];
 };
 struct linux_fchownat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)];
+	char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)];
+	char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)];
 };
 struct linux_futimesat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char utimes_l_[PADL_(struct l_timeval *)]; struct l_timeval * utimes; char utimes_r_[PADR_(struct l_timeval *)];
 };
 struct linux_fstatat64_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char pathname_l_[PADL_(char *)]; char * pathname; char pathname_r_[PADR_(char *)];
+	char statbuf_l_[PADL_(struct l_stat64 *)]; struct l_stat64 * statbuf; char statbuf_r_[PADR_(struct l_stat64 *)];
+	char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)];
 };
 struct linux_unlinkat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char pathname_l_[PADL_(char *)]; char * pathname; char pathname_r_[PADR_(char *)];
+	char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)];
 };
 struct linux_renameat_args {
-	register_t dummy;
+	char olddfd_l_[PADL_(l_int)]; l_int olddfd; char olddfd_r_[PADR_(l_int)];
+	char oldname_l_[PADL_(char *)]; char * oldname; char oldname_r_[PADR_(char *)];
+	char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)];
+	char newname_l_[PADL_(char *)]; char * newname; char newname_r_[PADR_(char *)];
 };
 struct linux_linkat_args {
-	register_t dummy;
+	char olddfd_l_[PADL_(l_int)]; l_int olddfd; char olddfd_r_[PADR_(l_int)];
+	char oldname_l_[PADL_(char *)]; char * oldname; char oldname_r_[PADR_(char *)];
+	char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)];
+	char newname_l_[PADL_(char *)]; char * newname; char newname_r_[PADR_(char *)];
+	char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
 };
 struct linux_symlinkat_args {
-	register_t dummy;
+	char oldname_l_[PADL_(char *)]; char * oldname; char oldname_r_[PADR_(char *)];
+	char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)];
+	char newname_l_[PADL_(char *)]; char * newname; char newname_r_[PADR_(char *)];
 };
 struct linux_readlinkat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
+	char bufsiz_l_[PADL_(l_int)]; l_int bufsiz; char bufsiz_r_[PADR_(l_int)];
 };
 struct linux_fchmodat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char mode_l_[PADL_(l_mode_t)]; l_mode_t mode; char mode_r_[PADR_(l_mode_t)];
 };
 struct linux_faccessat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)];
 };
 struct linux_pselect6_args {
 	register_t dummy;
---  amd64/linux32/linux32_syscall.h.orig
+++  amd64/linux32/linux32_syscall.h
@@ -2,7 +2,7 @@
  * System call numbers.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/amd64/linux32/linux32_syscall.h,v 1.31 2007/03/30 00:08:21 jkim Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.28 2007/03/30 00:06:21 jkim Exp 
  */
 
---  amd64/linux32/linux32_sysent.c.orig
+++  amd64/linux32/linux32_sysent.c
@@ -2,7 +2,7 @@
  * System call switch table.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/amd64/linux32/linux32_sysent.c,v 1.31 2007/03/30 00:08:21 jkim Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.28 2007/03/30 00:06:21 jkim Exp 
  */
 
@@ -316,18 +316,18 @@
 	{ 0, (sy_call_t *)linux_inotify_rm_watch, AUE_NULL, NULL, 0, 0 },	/* 293 = linux_inotify_rm_watch */
 	{ 0, (sy_call_t *)linux_migrate_pages, AUE_NULL, NULL, 0, 0 },	/* 294 = linux_migrate_pages */
 	{ AS(linux_openat_args), (sy_call_t *)linux_openat, AUE_OPEN_RWTC, NULL, 0, 0 },	/* 295 = linux_openat */
-	{ 0, (sy_call_t *)linux_mkdirat, AUE_NULL, NULL, 0, 0 },	/* 296 = linux_mkdirat */
-	{ 0, (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 },	/* 297 = linux_mknodat */
-	{ 0, (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 },	/* 298 = linux_fchownat */
-	{ 0, (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 },	/* 299 = linux_futimesat */
-	{ 0, (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 },	/* 300 = linux_fstatat64 */
-	{ 0, (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 },	/* 301 = linux_unlinkat */
-	{ 0, (sy_call_t *)linux_renameat, AUE_NULL, NULL, 0, 0 },	/* 302 = linux_renameat */
-	{ 0, (sy_call_t *)linux_linkat, AUE_NULL, NULL, 0, 0 },	/* 303 = linux_linkat */
-	{ 0, (sy_call_t *)linux_symlinkat, AUE_NULL, NULL, 0, 0 },	/* 304 = linux_symlinkat */
-	{ 0, (sy_call_t *)linux_readlinkat, AUE_NULL, NULL, 0, 0 },	/* 305 = linux_readlinkat */
-	{ 0, (sy_call_t *)linux_fchmodat, AUE_NULL, NULL, 0, 0 },	/* 306 = linux_fchmodat */
-	{ 0, (sy_call_t *)linux_faccessat, AUE_NULL, NULL, 0, 0 },	/* 307 = linux_faccessat */
+	{ AS(linux_mkdirat_args), (sy_call_t *)linux_mkdirat, AUE_NULL, NULL, 0, 0 },	/* 296 = linux_mkdirat */
+	{ AS(linux_mknodat_args), (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 },	/* 297 = linux_mknodat */
+	{ AS(linux_fchownat_args), (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 },	/* 298 = linux_fchownat */
+	{ AS(linux_futimesat_args), (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 },	/* 299 = linux_futimesat */
+	{ AS(linux_fstatat64_args), (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 },	/* 300 = linux_fstatat64 */
+	{ AS(linux_unlinkat_args), (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 },	/* 301 = linux_unlinkat */
+	{ AS(linux_renameat_args), (sy_call_t *)linux_renameat, AUE_NULL, NULL, 0, 0 },	/* 302 = linux_renameat */
+	{ AS(linux_linkat_args), (sy_call_t *)linux_linkat, AUE_NULL, NULL, 0, 0 },	/* 303 = linux_linkat */
+	{ AS(linux_symlinkat_args), (sy_call_t *)linux_symlinkat, AUE_NULL, NULL, 0, 0 },	/* 304 = linux_symlinkat */
+	{ AS(linux_readlinkat_args), (sy_call_t *)linux_readlinkat, AUE_NULL, NULL, 0, 0 },	/* 305 = linux_readlinkat */
+	{ AS(linux_fchmodat_args), (sy_call_t *)linux_fchmodat, AUE_NULL, NULL, 0, 0 },	/* 306 = linux_fchmodat */
+	{ AS(linux_faccessat_args), (sy_call_t *)linux_faccessat, AUE_NULL, NULL, 0, 0 },	/* 307 = linux_faccessat */
 	{ 0, (sy_call_t *)linux_pselect6, AUE_NULL, NULL, 0, 0 },	/* 308 = linux_pselect6 */
 	{ 0, (sy_call_t *)linux_ppoll, AUE_NULL, NULL, 0, 0 },	/* 309 = linux_ppoll */
 	{ 0, (sy_call_t *)linux_unshare, AUE_NULL, NULL, 0, 0 },	/* 310 = linux_unshare */
---  amd64/linux32/linux32_sysvec.c.orig
+++  amd64/linux32/linux32_sysvec.c
@@ -43,6 +43,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/exec.h>
+#include <sys/fcntl.h>
 #include <sys/imgact.h>
 #include <sys/imgact_elf.h>
 #include <sys/kernel.h>
@@ -787,7 +788,7 @@
 	     */
 	    if ((error = exec_shell_imgact(imgp)) == 0) {
 		    linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc),
-			imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0);
+			imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0, AT_FDCWD);
 		    if (rpath != NULL) {
 			    len = strlen(rpath) + 1;
 
---  amd64/linux32/syscalls.master.orig
+++  amd64/linux32/syscalls.master
@@ -465,18 +465,24 @@
 294	AUE_NULL	STD	{ int linux_migrate_pages(void); }
 295	AUE_OPEN_RWTC	STD	{ int linux_openat(l_int dfd, char *filename, \
 					l_int flags, l_int mode); }
-296	AUE_NULL	STD	{ int linux_mkdirat(void); }
-297	AUE_NULL	STD	{ int linux_mknodat(void); }
-298	AUE_NULL	STD	{ int linux_fchownat(void); }
-299	AUE_NULL	STD	{ int linux_futimesat(void); }
-300	AUE_NULL	STD	{ int linux_fstatat64(void); }
-301	AUE_NULL	STD	{ int linux_unlinkat(void); }
-302	AUE_NULL	STD	{ int linux_renameat(void); }
-303	AUE_NULL	STD	{ int linux_linkat(void); }
-304	AUE_NULL	STD	{ int linux_symlinkat(void); }
-305	AUE_NULL	STD	{ int linux_readlinkat(void); }
-306	AUE_NULL	STD	{ int linux_fchmodat(void); }
-307	AUE_NULL	STD	{ int linux_faccessat(void); }
+296	AUE_NULL	STD	{ int linux_mkdirat(l_int dfd, char *pathname, l_int mode); }
+297	AUE_NULL	STD	{ int linux_mknodat(l_int dfd, char *filename, l_int mode, l_uint dev); }
+298	AUE_NULL	STD	{ int linux_fchownat(l_int dfd, char *filename, \
+					l_uid16_t uid, l_gid16_t gid, l_int flag); }
+299	AUE_NULL	STD	{ int linux_futimesat(l_int dfd, char *filename, struct l_timeval *utimes); }
+300	AUE_NULL	STD	{ int linux_fstatat64(l_int dfd, char *pathname, \
+					struct l_stat64 *statbuf, l_int flag); }
+301	AUE_NULL	STD	{ int linux_unlinkat(l_int dfd, char *pathname, l_int flag); }
+302	AUE_NULL	STD	{ int linux_renameat(l_int olddfd, char *oldname, l_int newdfd, \
+					char *newname); }
+303	AUE_NULL	STD	{ int linux_linkat(l_int olddfd, char *oldname, \
+					l_int newdfd, char *newname, l_int flags); }
+304	AUE_NULL	STD	{ int linux_symlinkat(char *oldname, l_int newdfd, char *newname); }
+305	AUE_NULL	STD	{ int linux_readlinkat(l_int dfd, char *path, \
+					char *buf, l_int bufsiz); }
+306	AUE_NULL	STD	{ int linux_fchmodat(l_int dfd, char *filename, \
+					l_mode_t mode); }
+307	AUE_NULL	STD	{ int linux_faccessat(l_int dfd, char *filename, l_int mode); }
 308	AUE_NULL	STD	{ int linux_pselect6(void); }
 309	AUE_NULL	STD	{ int linux_ppoll(void); }
 310	AUE_NULL	STD	{ int linux_unshare(void); }
---  compat/linux/linux_file.c.orig
+++  compat/linux/linux_file.c
@@ -67,6 +67,7 @@
 #include <machine/../linux/linux_proto.h>
 #endif
 #include <compat/linux/linux_util.h>
+#include <compat/linux/linux_file.h>
 
 int
 linux_creat(struct thread *td, struct linux_creat_args *args)
@@ -88,7 +89,7 @@
 
 
 static int
-linux_common_open(struct thread *td, char *path, int l_flags, int mode, int openat)
+linux_common_open(struct thread *td, char *path, int l_flags, int mode, int dirfd)
 {
     struct proc *p = td->td_proc;
     struct file *fp;
@@ -130,7 +131,10 @@
 	bsd_flags |= O_NOFOLLOW;
     /* XXX LINUX_O_NOATIME: unable to be easily implemented. */
 
-    error = kern_open(td, path, UIO_SYSSPACE, bsd_flags, mode);
+    if (dirfd != -1)
+	error = kern_openat(td, path, UIO_SYSSPACE, bsd_flags, mode, dirfd);
+    else
+	error = kern_open(td, path, UIO_SYSSPACE, bsd_flags, mode);
     if (!error) {
 	    fd = td->td_retval[0];
 	    /*
@@ -172,115 +176,33 @@
     if (ldebug(open))
 	    printf(LMSG("open returns error %d"), error);
 #endif
-    if (!openat)
-	LFREEPATH(path);
+    LFREEPATH(path);
     return error;
 }
 
-/*
- * common code for linux *at set of syscalls
- *
- * works like this:
- * if filename is absolute 
- *    ignore dirfd
- * else
- *    if dirfd == AT_FDCWD 
- *       return CWD/filename
- *    else
- *       return DIRFD/filename
- */
-static int
-linux_at(struct thread *td, int dirfd, char *filename, char **newpath, char **freebuf)
-{
-   	struct file *fp;
-	int error = 0, vfslocked;
-	struct vnode *dvp;
-	struct filedesc *fdp = td->td_proc->p_fd;
-	char *fullpath = "unknown";
-	char *freepath = NULL;
-
-	/* don't do anything if the pathname is absolute */
-	if (*filename == '/') {
-	   	*newpath= filename;
-	   	return (0);
-	}
-
-	/* check for AT_FDWCD */
-	if (dirfd == LINUX_AT_FDCWD) {
-	   	FILEDESC_SLOCK(fdp);
-		dvp = fdp->fd_cdir;
-		vref(dvp);
-	   	FILEDESC_SUNLOCK(fdp);
-	} else {
-	   	error = fget(td, dirfd, &fp);
-		if (error)
-		   	return (error);
-		dvp = fp->f_vnode;
-		/* only a dir can be dfd */
-		if (dvp->v_type != VDIR) {
-		   	fdrop(fp, td);
-			return (ENOTDIR);
-		}
-		vref(dvp);
-		fdrop(fp, td);
-	}
-
-	/*
-	 * XXXRW: This is bogus, as vn_fullpath() returns only an advisory
-	 * file path, and may fail in several common situations, including
-	 * for file systmes that don't use the name cache, and if the entry
-	 * for the file falls out of the name cache.  We should implement
-	 * openat() in the FreeBSD native system call layer properly (using a
-	 * requested starting directory), and have Linux and other ABIs wrap
-	 * the native implementation.
-	 */
-	error = vn_fullpath(td, dvp, &fullpath, &freepath);
-	if (!error) {
-	   	*newpath = malloc(strlen(fullpath) + strlen(filename) + 2, M_TEMP, M_WAITOK | M_ZERO);
-		*freebuf = freepath;
-		sprintf(*newpath, "%s/%s", fullpath, filename);
-	} else {
-		*newpath = NULL;
-	}
-	vfslocked = VFS_LOCK_GIANT(dvp->v_mount);
-	vrele(dvp);
-	VFS_UNLOCK_GIANT(vfslocked);
-	return (error);
-}
-
 int
 linux_openat(struct thread *td, struct linux_openat_args *args)
 {
-   	char *newpath, *oldpath, *freebuf = NULL, *path;
-	int error;
+   	char *path;
+	int dfd;
+
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->dfd;
 
-	oldpath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
-	error = copyinstr(args->filename, oldpath, MAXPATHLEN, NULL);
+    	if (args->flags & LINUX_O_CREAT)
+		LCONVPATH_AT(td, args->filename, &path, 1, dfd);
+    	else
+		LCONVPATH_AT(td, args->filename, &path, 0, dfd);
 
 #ifdef DEBUG
 	if (ldebug(openat))
 		printf(ARGS(openat, "%i, %s, 0x%x, 0x%x"), args->dfd,
-		    oldpath, args->flags, args->mode);
+		    path, args->flags, args->mode);
 #endif
 
-	error = linux_at(td, args->dfd, oldpath, &newpath, &freebuf);
-	if (error)
-	   	return (error);
-#ifdef DEBUG
-	printf(LMSG("newpath: %s"), newpath);
-#endif
-    	if (args->flags & LINUX_O_CREAT)
-		LCONVPATH_SEG(td, newpath, &path, 1, UIO_SYSSPACE);
-    	else
-		LCONVPATH_SEG(td, newpath, &path, 0, UIO_SYSSPACE);
-	if (freebuf)
-	   	free(freebuf, M_TEMP);
-	if (*oldpath != '/')
-   	   	free(newpath, M_TEMP);
-
-	error = linux_common_open(td, path, args->flags, args->mode, 1);
-	free(oldpath, M_TEMP);
-	return (error);
+	return linux_common_open(td, path, args->flags, args->mode, dfd);
 }
 
 int
@@ -299,7 +221,7 @@
 		    path, args->flags, args->mode);
 #endif
 
-    return linux_common_open(td, path, args->flags, args->mode, 0);
+    return linux_common_open(td, path, args->flags, args->mode, -1);
 }
 
 int
@@ -649,6 +571,34 @@
 }
 
 int
+linux_faccessat(struct thread *td, struct linux_faccessat_args *args)
+{
+	char *path;
+	int error, dfd;
+
+	/* linux convention */
+	if (args->mode & ~(F_OK | X_OK | W_OK | R_OK))
+		return (EINVAL);
+
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = -1;
+	else
+		dfd = args->dfd;
+
+	LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
+
+#ifdef DEBUG
+	if (ldebug(access))
+		printf(ARGS(access, "%s, %d"), path, args->mode);
+#endif
+
+	error = kern_accessat(td, path, UIO_SYSSPACE, args->mode, dfd);
+	LFREEPATH(path);
+
+	return (error);
+}
+
+int
 linux_unlink(struct thread *td, struct linux_unlink_args *args)
 {
 	char *path;
@@ -673,6 +623,40 @@
 }
 
 int
+linux_unlinkat(struct thread *td, struct linux_unlinkat_args *args)
+{
+	char *path;
+	int error, dfd;
+	struct stat st;
+
+	if (args->flag & ~LINUX_AT_REMOVEDIR)
+		return (EINVAL);
+
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->dfd;
+
+	LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
+
+#ifdef DEBUG
+	if (ldebug(unlinkat))
+		printf(ARGS(unlinkat, "%s"), path);
+#endif
+
+	if (args->flag & LINUX_AT_REMOVEDIR)
+		error = kern_rmdirat(td, path, UIO_SYSSPACE, dfd);
+	else
+		error = kern_unlinkat(td, path, UIO_SYSSPACE, dfd);
+	if (error == EPERM)
+		/* Introduce POSIX noncompliant behaviour of Linux */
+		if (kern_statat(td, path, UIO_SYSSPACE, &st, dfd) == 0)
+			if (S_ISDIR(st.st_mode))
+				error = EISDIR;
+	LFREEPATH(path);
+	return (error);
+}
+int
 linux_chdir(struct thread *td, struct linux_chdir_args *args)
 {
 	char *path;
@@ -707,6 +691,29 @@
 }
 
 int
+linux_fchmodat(struct thread *td, struct linux_fchmodat_args *args)
+{
+	char *path;
+	int error, dfd;
+
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->dfd;
+
+	LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
+
+#ifdef DEBUG
+	if (ldebug(fchmodat))
+		printf(ARGS(fchmodat, "%s, %d"), path, args->mode);
+#endif
+
+	error = kern_chmodat(td, path, UIO_SYSSPACE, args->mode, dfd);
+	LFREEPATH(path);
+	return (error);
+}
+
+int
 linux_mkdir(struct thread *td, struct linux_mkdir_args *args)
 {
 	char *path;
@@ -724,6 +731,28 @@
 }
 
 int
+linux_mkdirat(struct thread *td, struct linux_mkdirat_args *args)
+{
+	char *path;
+	int error, dfd;
+
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->dfd;
+
+	LCONVPATHCREAT_AT(td, args->pathname, &path, dfd);
+
+#ifdef DEBUG
+	if (ldebug(mkdirat))
+		printf(ARGS(mkdirat, "%s, %d"), path, args->mode);
+#endif
+	error = kern_mkdirat(td, path, UIO_SYSSPACE, args->mode, dfd);
+	LFREEPATH(path);
+	return (error);
+}
+
+int
 linux_rmdir(struct thread *td, struct linux_rmdir_args *args)
 {
 	char *path;
@@ -748,7 +777,7 @@
 
 	LCONVPATHEXIST(td, args->from, &from);
 	/* Expand LCONVPATHCREATE so that `from' can be freed on errors */
-	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1);
+	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
 	if (to == NULL) {
 		LFREEPATH(from);
 		return (error);
@@ -765,6 +794,40 @@
 }
 
 int
+linux_renameat(struct thread *td, struct linux_renameat_args *args)
+{
+	char *from, *to;
+	int error, olddfd, newdfd;
+
+	if (args->olddfd == LINUX_AT_FDCWD)
+		olddfd = AT_FDCWD;
+	else
+		olddfd = args->olddfd;
+
+	if (args->newdfd == LINUX_AT_FDCWD)
+		newdfd = AT_FDCWD;
+	else
+		newdfd = args->newdfd;
+
+	LCONVPATHEXIST_AT(td, args->oldname, &from, olddfd);
+	/* Expand LCONVPATHCREATE so that `from' can be freed on errors */
+	error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd);
+	if (to == NULL) {
+		LFREEPATH(from);
+		return (error);
+	}
+
+#ifdef DEBUG
+	if (ldebug(renameat))
+		printf(ARGS(renameat, "%s, %s"), from, to);
+#endif
+	error = kern_renameat(td, from, to, UIO_SYSSPACE, olddfd, newdfd);
+	LFREEPATH(from);
+	LFREEPATH(to);
+	return (error);
+}
+
+int
 linux_symlink(struct thread *td, struct linux_symlink_args *args)
 {
 	char *path, *to;
@@ -772,7 +835,7 @@
 
 	LCONVPATHEXIST(td, args->path, &path);
 	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
-	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1);
+	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
 	if (to == NULL) {
 		LFREEPATH(path);
 		return (error);
@@ -789,6 +852,36 @@
 }
 
 int
+linux_symlinkat(struct thread *td, struct linux_symlinkat_args *args)
+{
+	char *path, *to;
+	int error, dfd;
+
+	if (args->newdfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->newdfd;
+
+	LCONVPATHEXIST_AT(td, args->oldname, &path, dfd);
+	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
+	error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, dfd);
+	if (to == NULL) {
+		LFREEPATH(path);
+		return (error);
+	}
+
+#ifdef DEBUG
+	if (ldebug(symlinkat))
+		printf(ARGS(symlinkat, "%s, %s"), path, to);
+#endif
+
+	error = kern_symlinkat(td, path, to, UIO_SYSSPACE, dfd);
+	LFREEPATH(path);
+	LFREEPATH(to);
+	return (error);
+}
+
+int
 linux_readlink(struct thread *td, struct linux_readlink_args *args)
 {
 	char *name;
@@ -808,6 +901,30 @@
 }
 
 int
+linux_readlinkat(struct thread *td, struct linux_readlinkat_args *args)
+{
+	char *name;
+	int error, dfd;
+
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->dfd;
+
+	LCONVPATHEXIST_AT(td, args->path, &name, dfd);
+
+#ifdef DEBUG
+	if (ldebug(readlinkat))
+		printf(ARGS(readlinkat, "%s, %p, %d"), name, (void *)args->buf,
+		    args->bufsiz);
+#endif
+
+	error = kern_readlinkat(td, name, UIO_SYSSPACE, args->buf, UIO_USERSPACE,
+	    args->bufsiz, dfd);
+	LFREEPATH(name);
+	return (error);
+}
+int
 linux_truncate(struct thread *td, struct linux_truncate_args *args)
 {
 	char *path;
@@ -848,7 +965,7 @@
 
 	LCONVPATHEXIST(td, args->path, &path);
 	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
-	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1);
+	error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
 	if (to == NULL) {
 		LFREEPATH(path);
 		return (error);
@@ -865,6 +982,49 @@
 }
 
 int
+linux_linkat(struct thread *td, struct linux_linkat_args *args)
+{
+	char *path, *to;
+	int error, olddfd, newdfd;
+
+	/* 
+	 * don't laugh they really introduced flags argument
+	 * which is forbidden to use ;)
+	 */
+	if (args->flags != 0)
+		return (EINVAL);
+
+	if (args->olddfd == LINUX_AT_FDCWD)
+		olddfd = AT_FDCWD;
+	else
+		olddfd = args->olddfd;
+
+	if (args->newdfd == LINUX_AT_FDCWD)
+		newdfd = AT_FDCWD;
+	else
+		newdfd = args->newdfd;
+
+	LCONVPATHEXIST_AT(td, args->oldname, &path, olddfd);
+	/* Expand LCONVPATHCREATE so that `path' can be freed on errors */
+	error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd);
+	if (to == NULL) {
+		LFREEPATH(path);
+		return (error);
+	}
+
+#ifdef DEBUG
+	if (ldebug(linkat))
+		printf(ARGS(linkat, "%i, %s, %i, %s, %i"), args->olddfd, path,
+			args->newdfd, to, args->flags);
+#endif
+
+	error = kern_linkat(td, path, to, UIO_SYSSPACE, olddfd, newdfd, FOLLOW);
+	LFREEPATH(path);
+	LFREEPATH(to);
+	return (error);
+}
+
+int
 linux_fdatasync(td, uap)
 	struct thread *td;
 	struct linux_fdatasync_args *uap;
@@ -1330,6 +1490,35 @@
 }
 
 int
+linux_fchownat(struct thread *td, struct linux_fchownat_args *args)
+{
+	char *path;
+	int error, dfd;
+
+	if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
+		return (EINVAL);	
+
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->dfd;
+
+	LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
+
+#ifdef DEBUG
+	if (ldebug(fchownat))
+		printf(ARGS(fchownat, "%s, %d, %d"), path, args->uid, args->gid);
+#endif
+
+	if (args->flag & LINUX_AT_SYMLINK_NOFOLLOW)
+		error = kern_lchownat(td, path, UIO_SYSSPACE, args->uid, args->gid, dfd);
+	else
+		error = kern_chownat(td, path, UIO_SYSSPACE, args->uid, args->gid, dfd);
+	LFREEPATH(path);
+	return (error);
+}
+
+int
 linux_lchown(struct thread *td, struct linux_lchown_args *args)
 {
 	char *path;
--- /dev/null	Wed Jun 27 16:22:00 2007
+++ //depot/projects/soc2007/rdivacky/linux_at/sys/compat/linux/linux_file.h	Wed Jun 27 16:25:48 2007
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2007 Roman Divacky
+ * 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
+ *    in this position and unchanged.
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_FILE_H_
+#define	_LINUX_FILE_H_
+
+#define	LINUX_AT_FDCWD			-100
+#define	LINUX_AT_SYMLINK_NOFOLLOW	0x100
+#define	LINUX_AT_REMOVEDIR		0x200
+
+#endif	/* !_LINUX_FILE_H_ */
--- compat/linux/linux_misc.c.orig
+++ compat/linux/linux_misc.c
@@ -86,6 +86,7 @@
 #include <machine/../linux/linux_proto.h>
 #endif
 
+#include <compat/linux/linux_file.h>
 #include <compat/linux/linux_mib.h>
 #include <compat/linux/linux_signal.h>
 #include <compat/linux/linux_util.h>
@@ -820,6 +821,43 @@
 	LFREEPATH(fname);
 	return (error);
 }
+
+int
+linux_futimesat(struct thread *td, struct linux_futimesat_args *args)
+{
+	l_timeval ltv[2];
+	struct timeval tv[2], *tvp = NULL;
+	char *fname;
+	int error, dfd;
+
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->dfd;
+
+	LCONVPATHEXIST_AT(td, args->filename, &fname, dfd);
+
+#ifdef DEBUG
+	if (ldebug(futimesat))
+		printf(ARGS(futimesat, "%s, *"), fname);
+#endif
+
+	if (args->utimes!= NULL) {
+		if ((error = copyin(args->utimes, ltv, sizeof ltv))) {
+			LFREEPATH(fname);
+			return (error);
+		}
+		tv[0].tv_sec = ltv[0].tv_sec;
+		tv[0].tv_usec = ltv[0].tv_usec;
+		tv[1].tv_sec = ltv[1].tv_sec;
+		tv[1].tv_usec = ltv[1].tv_usec;
+		tvp = tv;
+	}
+
+	error = kern_utimesat(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE, dfd);
+	LFREEPATH(fname);
+	return (error);
+}
 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
 
 #define __WCLONE 0x80000000
@@ -957,6 +995,56 @@
 	return (error);
 }
 
+int
+linux_mknodat(struct thread *td, struct linux_mknodat_args *args)
+{
+	char *path;
+	int error, dfd;
+
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->dfd;
+
+	LCONVPATHCREAT_AT(td, args->filename, &path, dfd);
+
+#ifdef DEBUG
+	if (ldebug(mknodat))
+		printf(ARGS(mknodat, "%s, %d, %d"), path, args->mode, args->dev);
+#endif
+
+	switch (args->mode & S_IFMT) {
+	case S_IFIFO:
+	case S_IFSOCK:
+		error = kern_mkfifoat(td, path, UIO_SYSSPACE, args->mode, dfd);
+		break;
+
+	case S_IFCHR:
+	case S_IFBLK:
+		error = kern_mknodat(td, path, UIO_SYSSPACE, args->mode,
+		    args->dev, dfd);
+		break;
+
+	case S_IFDIR:
+		error = EPERM;
+		break;
+
+	case 0:
+		args->mode |= S_IFREG;
+		/* FALLTHROUGH */
+	case S_IFREG:
+		error = kern_openat(td, path, UIO_SYSSPACE,
+		    O_WRONLY | O_CREAT | O_TRUNC, args->mode, dfd);
+		break;
+
+	default:
+		error = EINVAL;
+		break;
+	}
+	LFREEPATH(path);
+	return (error);
+}
+
 /*
  * UGH! This is just about the dumbest idea I've ever heard!!
  */
--- compat/linux/linux_stats.c.orig
+++ compat/linux/linux_stats.c
@@ -57,6 +57,7 @@
 #endif
 
 #include <compat/linux/linux_util.h>
+#include <compat/linux/linux_file.h>
 
 #include <security/mac/mac_framework.h>
 
@@ -132,6 +133,25 @@
 	fdclose(fdp, fdp->fd_ofiles[fd], fd, td);
 }
 
+static void
+translate_path_major_minor_at(struct thread *td, char *path, struct stat *buf, int dfd)
+{
+	struct proc *p = td->td_proc;	
+	struct filedesc *fdp = p->p_fd;
+	int fd;
+	int temp;
+
+	if (!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode))
+		return;
+	temp = td->td_retval[0];
+	if (kern_openat(td, path, UIO_SYSSPACE, O_RDONLY, 0, dfd) != 0)
+		return;
+	fd = td->td_retval[0];
+	td->td_retval[0] = temp;
+	translate_fd_major_minor(td, fd, buf);
+	fdclose(fdp, fdp->fd_ofiles[fd], fd, td);
+}
+
 static int
 newstat_copyout(struct stat *buf, void *ubuf)
 {
@@ -578,4 +598,39 @@
 	return (error);
 }
 
+int
+linux_fstatat64(struct thread *td, struct linux_fstatat64_args *args)
+{
+	char *path;
+	int error, dfd;
+	struct stat buf;
+
+	if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
+		return (EINVAL);
+
+	if (args->dfd == LINUX_AT_FDCWD)
+		dfd = AT_FDCWD;
+	else
+		dfd = args->dfd;
+
+	LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
+
+#ifdef DEBUG
+	if (ldebug(fstatat64))
+		printf(ARGS(fstatat64, "%i, %s, %i"), args->dfd, path, args->flag);
+#endif
+
+	if (args->flag & LINUX_AT_SYMLINK_NOFOLLOW)
+		error = kern_lstatat(td, path, UIO_SYSSPACE, &buf, dfd);
+	else
+		error = kern_statat(td, path, UIO_SYSSPACE, &buf, dfd);
+		
+	translate_path_major_minor_at(td, args->pathname, &buf, dfd);
+	if (!error)
+		error = stat64_copyout(&buf, args->statbuf);
+	LFREEPATH(path);
+	
+	return (error);
+}
+
 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
--- compat/linux/linux_uid16.c.orig
+++ compat/linux/linux_uid16.c
@@ -29,6 +29,7 @@
 
 #include "opt_compat.h"
 
+#include <sys/fcntl.h>
 #include <sys/param.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
--- compat/linux/linux_util.c.orig
+++ compat/linux/linux_util.c
@@ -36,6 +36,7 @@
 
 #include <sys/param.h>
 #include <sys/bus.h>
+#include <sys/fcntl.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/linker_set.h>
@@ -65,16 +66,17 @@
  * named file, i.e. we check if the directory it should be in exists.
  */
 int
-linux_emul_convpath(td, path, pathseg, pbuf, cflag)
+linux_emul_convpath(td, path, pathseg, pbuf, cflag, dfd)
 	struct thread	 *td;
 	char		 *path;
 	enum uio_seg	  pathseg;
 	char		**pbuf;
 	int		  cflag;
+	int		  dfd;		
 {
 
-	return (kern_alternate_path(td, linux_emul_path, path, pathseg, pbuf,
-		cflag));
+	return kern_alternate_path(td, linux_emul_path, path, pathseg, pbuf,
+		cflag, dfd);
 }
 
 void
--- compat/linux/linux_util.h.orig
+++ compat/linux/linux_util.h
@@ -51,23 +51,25 @@
 
 extern const char linux_emul_path[];
 
-int linux_emul_convpath(struct thread *, char *, enum uio_seg, char **, int);
+int linux_emul_convpath(struct thread *, char *, enum uio_seg, char **, int, int);
 
-#define LCONVPATH_SEG(td, upath, pathp, i, seg)				\
+#define LCONVPATH_AT(td, upath, pathp, i, dfd)				\
 	do {								\
 		int _error;						\
 									\
-		_error = linux_emul_convpath(td, upath, seg,		\
-		    pathp, i);						\
+		_error = linux_emul_convpath(td, upath, UIO_USERSPACE,	\
+		    pathp, i, dfd);					\
 		if (*(pathp) == NULL)					\
 			return (_error);				\
 	} while (0)
 
 #define LCONVPATH(td, upath, pathp, i) 	\
-   LCONVPATH_SEG(td, upath, pathp, i, UIO_USERSPACE)
+   LCONVPATH_AT(td, upath, pathp, i, AT_FDCWD)
 
 #define LCONVPATHEXIST(td, upath, pathp) LCONVPATH(td, upath, pathp, 0)
+#define LCONVPATHEXIST_AT(td, upath, pathp, dfd) LCONVPATH_AT(td, upath, pathp, 0, dfd)
 #define LCONVPATHCREAT(td, upath, pathp) LCONVPATH(td, upath, pathp, 1)
+#define LCONVPATHCREAT_AT(td, upath, pathp, dfd) LCONVPATH_AT(td, upath, pathp, 1, dfd)
 #define LFREEPATH(path)	free(path, M_TEMP)
 
 #define DUMMY(s)							\
--- compat/svr4/svr4_sysvec.c.orig
+++ compat/svr4/svr4_sysvec.c
@@ -44,6 +44,7 @@
 #include <sys/sysent.h>
 #include <sys/imgact.h>
 #include <sys/imgact_elf.h>
+#include <sys/fcntl.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
@@ -258,7 +259,7 @@
 {
 
 	return (kern_alternate_path(td, svr4_emul_path, path, pathseg, pbuf,
-	    create));
+	    create, AT_FDCWD));
 }
 
 static int
--- i386/ibcs2/ibcs2_util.c.orig
+++ i386/ibcs2/ibcs2_util.c
@@ -32,6 +32,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD: src/sys/i386/ibcs2/ibcs2_util.c,v 1.19 2005/02/07 22:02:18 jhb Exp $");
 
+#include <sys/fcntl.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/syscallsubr.h>
@@ -55,5 +56,5 @@
 {
 
 	return (kern_alternate_path(td, ibcs2_emul_path, path, pathseg, pbuf,
-	    cflag));
+	    cflag, AT_FDCWD));
 }
--- i386/linux/linux.h.orig
+++ i386/linux/linux.h
@@ -537,8 +537,6 @@
 #define	LINUX_F_WRLCK		1
 #define	LINUX_F_UNLCK		2
 
-#define	LINUX_AT_FDCWD		-100
-
 /*
  * mount flags
  */
--- i386/linux/linux_dummy.c.orig
+++ i386/linux/linux_dummy.c
@@ -87,18 +87,6 @@
 DUMMY(inotify_add_watch);
 DUMMY(inotify_rm_watch);
 DUMMY(migrate_pages);
-DUMMY(mkdirat);
-DUMMY(mknodat);
-DUMMY(fchownat);
-DUMMY(futimesat);
-DUMMY(fstatat64);
-DUMMY(unlinkat);
-DUMMY(renameat);
-DUMMY(linkat);
-DUMMY(symlinkat);
-DUMMY(readlinkat);
-DUMMY(fchmodat);
-DUMMY(faccessat);
 DUMMY(pselect6);
 DUMMY(ppoll);
 DUMMY(unshare);
--- i386/linux/linux_proto.h.orig
+++ i386/linux/linux_proto.h
@@ -2,8 +2,8 @@
  * System call prototypes.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/i386/linux/linux_proto.h,v 1.92 2007/03/29 02:11:46 julian Exp $
- * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.86 2007/02/15 00:54:40 jkim Exp 
+ * $FreeBSD$
+ * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.87 2007/03/29 02:11:46 julian Exp 
  */
 
 #ifndef _LINUX_SYSPROTO_H_
@@ -899,40 +899,72 @@
 	char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)];
 };
 struct linux_mkdirat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char pathname_l_[PADL_(char *)]; char * pathname; char pathname_r_[PADR_(char *)];
+	char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)];
 };
 struct linux_mknodat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)];
+	char dev_l_[PADL_(l_uint)]; l_uint dev; char dev_r_[PADR_(l_uint)];
 };
 struct linux_fchownat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char uid_l_[PADL_(l_uid16_t)]; l_uid16_t uid; char uid_r_[PADR_(l_uid16_t)];
+	char gid_l_[PADL_(l_gid16_t)]; l_gid16_t gid; char gid_r_[PADR_(l_gid16_t)];
+	char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)];
 };
 struct linux_futimesat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char utimes_l_[PADL_(struct l_timeval *)]; struct l_timeval * utimes; char utimes_r_[PADR_(struct l_timeval *)];
 };
 struct linux_fstatat64_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char pathname_l_[PADL_(char *)]; char * pathname; char pathname_r_[PADR_(char *)];
+	char statbuf_l_[PADL_(struct l_stat64 *)]; struct l_stat64 * statbuf; char statbuf_r_[PADR_(struct l_stat64 *)];
+	char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)];
 };
 struct linux_unlinkat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char pathname_l_[PADL_(char *)]; char * pathname; char pathname_r_[PADR_(char *)];
+	char flag_l_[PADL_(l_int)]; l_int flag; char flag_r_[PADR_(l_int)];
 };
 struct linux_renameat_args {
-	register_t dummy;
+	char olddfd_l_[PADL_(l_int)]; l_int olddfd; char olddfd_r_[PADR_(l_int)];
+	char oldname_l_[PADL_(char *)]; char * oldname; char oldname_r_[PADR_(char *)];
+	char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)];
+	char newname_l_[PADL_(char *)]; char * newname; char newname_r_[PADR_(char *)];
 };
 struct linux_linkat_args {
-	register_t dummy;
+	char olddfd_l_[PADL_(l_int)]; l_int olddfd; char olddfd_r_[PADR_(l_int)];
+	char oldname_l_[PADL_(char *)]; char * oldname; char oldname_r_[PADR_(char *)];
+	char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)];
+	char newname_l_[PADL_(char *)]; char * newname; char newname_r_[PADR_(char *)];
+	char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
 };
 struct linux_symlinkat_args {
-	register_t dummy;
+	char oldname_l_[PADL_(char *)]; char * oldname; char oldname_r_[PADR_(char *)];
+	char newdfd_l_[PADL_(l_int)]; l_int newdfd; char newdfd_r_[PADR_(l_int)];
+	char newname_l_[PADL_(char *)]; char * newname; char newname_r_[PADR_(char *)];
 };
 struct linux_readlinkat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
+	char bufsiz_l_[PADL_(l_int)]; l_int bufsiz; char bufsiz_r_[PADR_(l_int)];
 };
 struct linux_fchmodat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char mode_l_[PADL_(l_mode_t)]; l_mode_t mode; char mode_r_[PADR_(l_mode_t)];
 };
 struct linux_faccessat_args {
-	register_t dummy;
+	char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
+	char filename_l_[PADL_(char *)]; char * filename; char filename_r_[PADR_(char *)];
+	char mode_l_[PADL_(l_int)]; l_int mode; char mode_r_[PADR_(l_int)];
 };
 struct linux_pselect6_args {
 	register_t dummy;
--- i386/linux/linux_syscall.h.orig
+++ i386/linux/linux_syscall.h
@@ -2,8 +2,8 @@
  * System call numbers.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/i386/linux/linux_syscall.h,v 1.85 2007/03/29 02:11:46 julian Exp $
- * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.86 2007/02/15 00:54:40 jkim Exp 
+ * $FreeBSD$
+ * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.87 2007/03/29 02:11:46 julian Exp 
  */
 
 #define	LINUX_SYS_exit	1
--- i386/linux/linux_sysent.c.orig
+++ i386/linux/linux_sysent.c
@@ -2,8 +2,8 @@
  * System call switch table.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/i386/linux/linux_sysent.c,v 1.92 2007/03/29 02:11:46 julian Exp $
- * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.86 2007/02/15 00:54:40 jkim Exp 
+ * $FreeBSD$
+ * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.87 2007/03/29 02:11:46 julian Exp 
  */
 
 #include <bsm/audit_kevents.h>
@@ -315,18 +315,18 @@
 	{ 0, (sy_call_t *)linux_inotify_rm_watch, AUE_NULL, NULL, 0, 0 },	/* 293 = linux_inotify_rm_watch */
 	{ 0, (sy_call_t *)linux_migrate_pages, AUE_NULL, NULL, 0, 0 },	/* 294 = linux_migrate_pages */
 	{ AS(linux_openat_args), (sy_call_t *)linux_openat, AUE_OPEN_RWTC, NULL, 0, 0 },	/* 295 = linux_openat */
-	{ 0, (sy_call_t *)linux_mkdirat, AUE_NULL, NULL, 0, 0 },	/* 296 = linux_mkdirat */
-	{ 0, (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 },	/* 297 = linux_mknodat */
-	{ 0, (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 },	/* 298 = linux_fchownat */
-	{ 0, (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 },	/* 299 = linux_futimesat */
-	{ 0, (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 },	/* 300 = linux_fstatat64 */
-	{ 0, (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 },	/* 301 = linux_unlinkat */
-	{ 0, (sy_call_t *)linux_renameat, AUE_NULL, NULL, 0, 0 },	/* 302 = linux_renameat */
-	{ 0, (sy_call_t *)linux_linkat, AUE_NULL, NULL, 0, 0 },	/* 303 = linux_linkat */
-	{ 0, (sy_call_t *)linux_symlinkat, AUE_NULL, NULL, 0, 0 },	/* 304 = linux_symlinkat */
-	{ 0, (sy_call_t *)linux_readlinkat, AUE_NULL, NULL, 0, 0 },	/* 305 = linux_readlinkat */
-	{ 0, (sy_call_t *)linux_fchmodat, AUE_NULL, NULL, 0, 0 },	/* 306 = linux_fchmodat */
-	{ 0, (sy_call_t *)linux_faccessat, AUE_NULL, NULL, 0, 0 },	/* 307 = linux_faccessat */
+	{ AS(linux_mkdirat_args), (sy_call_t *)linux_mkdirat, AUE_NULL, NULL, 0, 0 },	/* 296 = linux_mkdirat */
+	{ AS(linux_mknodat_args), (sy_call_t *)linux_mknodat, AUE_NULL, NULL, 0, 0 },	/* 297 = linux_mknodat */
+	{ AS(linux_fchownat_args), (sy_call_t *)linux_fchownat, AUE_NULL, NULL, 0, 0 },	/* 298 = linux_fchownat */
+	{ AS(linux_futimesat_args), (sy_call_t *)linux_futimesat, AUE_NULL, NULL, 0, 0 },	/* 299 = linux_futimesat */
+	{ AS(linux_fstatat64_args), (sy_call_t *)linux_fstatat64, AUE_NULL, NULL, 0, 0 },	/* 300 = linux_fstatat64 */
+	{ AS(linux_unlinkat_args), (sy_call_t *)linux_unlinkat, AUE_NULL, NULL, 0, 0 },	/* 301 = linux_unlinkat */
+	{ AS(linux_renameat_args), (sy_call_t *)linux_renameat, AUE_NULL, NULL, 0, 0 },	/* 302 = linux_renameat */
+	{ AS(linux_linkat_args), (sy_call_t *)linux_linkat, AUE_NULL, NULL, 0, 0 },	/* 303 = linux_linkat */
+	{ AS(linux_symlinkat_args), (sy_call_t *)linux_symlinkat, AUE_NULL, NULL, 0, 0 },	/* 304 = linux_symlinkat */
+	{ AS(linux_readlinkat_args), (sy_call_t *)linux_readlinkat, AUE_NULL, NULL, 0, 0 },	/* 305 = linux_readlinkat */
+	{ AS(linux_fchmodat_args), (sy_call_t *)linux_fchmodat, AUE_NULL, NULL, 0, 0 },	/* 306 = linux_fchmodat */
+	{ AS(linux_faccessat_args), (sy_call_t *)linux_faccessat, AUE_NULL, NULL, 0, 0 },	/* 307 = linux_faccessat */
 	{ 0, (sy_call_t *)linux_pselect6, AUE_NULL, NULL, 0, 0 },	/* 308 = linux_pselect6 */
 	{ 0, (sy_call_t *)linux_ppoll, AUE_NULL, NULL, 0, 0 },	/* 309 = linux_ppoll */
 	{ 0, (sy_call_t *)linux_unshare, AUE_NULL, NULL, 0, 0 },	/* 310 = linux_unshare */
--- i386/linux/linux_sysvec.c.orig
+++ i386/linux/linux_sysvec.c
@@ -32,6 +32,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/exec.h>
+#include <sys/fcntl.h>
 #include <sys/imgact.h>
 #include <sys/imgact_aout.h>
 #include <sys/imgact_elf.h>
@@ -775,7 +776,7 @@
 	     */
 	    if ((error = exec_shell_imgact(imgp)) == 0) {
 		    linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc),
-			imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0);
+			imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0, AT_FDCWD);
 		    if (rpath != NULL) {
 			    len = strlen(rpath) + 1;
 
--- i386/linux/syscalls.master.orig
+++ i386/linux/syscalls.master
@@ -475,18 +475,24 @@
 294	AUE_NULL	STD	{ int linux_migrate_pages(void); }
 295	AUE_OPEN_RWTC	STD	{ int linux_openat(l_int dfd, char *filename, \
 					l_int flags, l_int mode); }
-296	AUE_NULL	STD	{ int linux_mkdirat(void); }
-297	AUE_NULL	STD	{ int linux_mknodat(void); }
-298	AUE_NULL	STD	{ int linux_fchownat(void); }
-299	AUE_NULL	STD	{ int linux_futimesat(void); }
-300	AUE_NULL	STD	{ int linux_fstatat64(void); }
-301	AUE_NULL	STD	{ int linux_unlinkat(void); }
-302	AUE_NULL	STD	{ int linux_renameat(void); }
-303	AUE_NULL	STD	{ int linux_linkat(void); }
-304	AUE_NULL	STD	{ int linux_symlinkat(void); }
-305	AUE_NULL	STD	{ int linux_readlinkat(void); }
-306	AUE_NULL	STD	{ int linux_fchmodat(void); }
-307	AUE_NULL	STD	{ int linux_faccessat(void); }
+296	AUE_NULL	STD	{ int linux_mkdirat(l_int dfd, char *pathname, l_int mode); }
+297	AUE_NULL	STD	{ int linux_mknodat(l_int dfd, char *filename, l_int mode, l_uint dev); }
+298	AUE_NULL	STD	{ int linux_fchownat(l_int dfd, char *filename, \
+					l_uid16_t uid, l_gid16_t gid, l_int flag); }
+299	AUE_NULL	STD	{ int linux_futimesat(l_int dfd, char *filename, struct l_timeval *utimes); }
+300	AUE_NULL	STD	{ int linux_fstatat64(l_int dfd, char *pathname, \
+					struct l_stat64 *statbuf, l_int flag); }
+301	AUE_NULL	STD	{ int linux_unlinkat(l_int dfd, char *pathname, l_int flag); }
+302	AUE_NULL	STD	{ int linux_renameat(l_int olddfd, char *oldname, l_int newdfd, \
+					char *newname); }
+303	AUE_NULL	STD	{ int linux_linkat(l_int olddfd, char *oldname, \
+					l_int newdfd, char *newname, l_int flags); }
+304	AUE_NULL	STD	{ int linux_symlinkat(char *oldname, l_int newdfd, char *newname); }
+305	AUE_NULL	STD	{ int linux_readlinkat(l_int dfd, char *path, \
+					char *buf, l_int bufsiz); }
+306	AUE_NULL	STD	{ int linux_fchmodat(l_int dfd, char *filename, \
+					l_mode_t mode); }
+307	AUE_NULL	STD	{ int linux_faccessat(l_int dfd, char *filename, l_int mode); }
 308	AUE_NULL	STD	{ int linux_pselect6(void); }
 309	AUE_NULL	STD	{ int linux_ppoll(void); }
 310	AUE_NULL	STD	{ int linux_unshare(void); }
--- kern/init_sysent.c.orig
+++ kern/init_sysent.c
@@ -2,7 +2,7 @@
  * System call switch table.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/kern/init_sysent.c,v 1.228 2006/11/11 22:01:25 ru Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.231 2006/11/03 15:23:14 rrs Exp 
  */
 
@@ -504,4 +504,19 @@
 	{ AS(sctp_generic_sendmsg_args), (sy_call_t *)sctp_generic_sendmsg, AUE_NULL, NULL, 0, 0 },	/* 472 = sctp_generic_sendmsg */
 	{ AS(sctp_generic_sendmsg_iov_args), (sy_call_t *)sctp_generic_sendmsg_iov, AUE_NULL, NULL, 0, 0 },	/* 473 = sctp_generic_sendmsg_iov */
 	{ AS(sctp_generic_recvmsg_args), (sy_call_t *)sctp_generic_recvmsg, AUE_NULL, NULL, 0, 0 },	/* 474 = sctp_generic_recvmsg */
+	{ AS(faccessat_args), (sy_call_t *)faccessat, AUE_ACCESS, NULL, 0, 0 },	/* 475 = faccessat */
+	{ AS(fchmodat_args), (sy_call_t *)fchmodat, AUE_CHMOD, NULL, 0, 0 },	/* 476 = fchmodat */
+	{ AS(fchownat_args), (sy_call_t *)fchownat, AUE_CHOWN, NULL, 0, 0 },	/* 477 = fchownat */
+	{ AS(fexecve_args), (sy_call_t *)fexecve, AUE_EXECVE, NULL, 0, 0 },	/* 478 = fexecve */
+	{ AS(fstatat_args), (sy_call_t *)fstatat, AUE_STAT, NULL, 0, 0 },	/* 479 = fstatat */
+	{ AS(futimesat_args), (sy_call_t *)futimesat, AUE_UTIMES, NULL, 0, 0 },	/* 480 = futimesat */
+	{ AS(linkat_args), (sy_call_t *)linkat, AUE_LINK, NULL, 0, 0 },	/* 481 = linkat */
+	{ AS(mkdirat_args), (sy_call_t *)mkdirat, AUE_MKDIR, NULL, 0, 0 },	/* 482 = mkdirat */
+	{ AS(mkfifoat_args), (sy_call_t *)mkfifoat, AUE_MKFIFO, NULL, 0, 0 },	/* 483 = mkfifoat */
+	{ AS(mknodat_args), (sy_call_t *)mknodat, AUE_MKNOD, NULL, 0, 0 },	/* 484 = mknodat */
+	{ AS(openat_args), (sy_call_t *)openat, AUE_OPEN_RWTC, NULL, 0, 0 },	/* 485 = openat */
+	{ AS(readlinkat_args), (sy_call_t *)readlinkat, AUE_READLINK, NULL, 0, 0 },	/* 486 = readlinkat */
+	{ AS(renameat_args), (sy_call_t *)renameat, AUE_RENAME, NULL, 0, 0 },	/* 487 = renameat */
+	{ AS(symlinkat_args), (sy_call_t *)symlinkat, AUE_SYMLINK, NULL, 0, 0 },	/* 488 = symlinkat */
+	{ AS(unlinkat_args), (sy_call_t *)unlinkat, AUE_UNLINK, NULL, 0, 0 },	/* 489 = unlinkat */
 };
--- kern/kern_exec.c.orig
+++ kern/kern_exec.c
@@ -188,6 +188,27 @@
 }
 
 #ifndef _SYS_SYSPROTO_H_
+struct fexecve_args {
+	int	fd;
+	char	**argv;
+	char	**envv;
+}
+#endif
+int
+fexecve(struct thread *td, struct fexecve_args *uap)
+{
+	int error;
+	struct image_args args;
+
+	error = exec_copyin_args(&args, NULL, UIO_SYSSPACE,
+	    uap->argv, uap->envv);
+	args.fd = uap->fd;
+	if (error == 0)
+		error = kern_execve(td, &args, NULL);
+	return (error);
+}
+
+#ifndef _SYS_SYSPROTO_H_
 struct __mac_execve_args {
 	char	*fname;
 	char	**argv;
@@ -293,7 +314,7 @@
 	struct vnode *tracevp = NULL;
 	struct ucred *tracecred = NULL;
 #endif
-	struct vnode *textvp = NULL;
+	struct vnode *textvp = NULL, *binvp = NULL;
 	int credential_changing;
 	int vfslocked;
 	int textset;
@@ -354,17 +375,29 @@
 	 * XXXAUDIT: It would be desirable to also audit the name of the
 	 * interpreter if this is an interpreted binary.
 	 */
-	ndp = &nd;
-	NDINIT(ndp, LOOKUP, ISOPEN | LOCKLEAF | FOLLOW | SAVENAME | MPSAFE |
-	    AUDITVNODE1, UIO_SYSSPACE, args->fname, td);
+	if (args->fname != NULL) {
+   		ndp = &nd;
+		NDINIT(ndp, LOOKUP, ISOPEN | LOCKLEAF | FOLLOW | SAVENAME 
+		    | MPSAFE | AUDITVNODE1, UIO_SYSSPACE, args->fname, td);
+	}
 
 interpret:
-	error = namei(ndp);
-	if (error)
-		goto exec_fail;
+	if (args->fname != NULL) {
+		error = namei(ndp);
+		if (error)
+			goto exec_fail;
 
-	vfslocked = NDHASGIANT(ndp);
-	imgp->vp = ndp->ni_vp;
+		vfslocked = NDHASGIANT(ndp);
+		binvp  = ndp->ni_vp;
+		imgp->vp = binvp;
+	} else {
+	   	error = fgetvp(td, args->fd, &binvp);
+		if (error)
+			goto exec_fail;
+		VOP_LOCK(binvp, LK_EXCLUSIVE, td);
+		vfslocked = VFS_NEEDSGIANT(binvp->v_mount);
+		imgp->vp = binvp;
+	}
 
 	/*
 	 * Check file permissions (also 'opens' file)
@@ -436,12 +469,13 @@
 		 */
 		imgp->vp->v_vflag &= ~VV_TEXT;
 		/* free name buffer and old vnode */
-		NDFREE(ndp, NDF_ONLY_PNBUF);
+		if (args->fname != NULL)
+   			NDFREE(ndp, NDF_ONLY_PNBUF);
 #ifdef MAC
 		interplabel = mac_vnode_label_alloc();
-		mac_copy_vnode_label(ndp->ni_vp->v_label, interplabel);
+		mac_copy_vnode_label(binvp->v_label, interplabel);
 #endif
-		vput(ndp->ni_vp);
+		vput(binvp);
 		vm_object_deallocate(imgp->object);
 		imgp->object = NULL;
 		VFS_UNLOCK_GIANT(vfslocked);
@@ -449,6 +483,7 @@
 		/* set new name to that of the interpreter */
 		NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME | MPSAFE,
 		    UIO_SYSSPACE, imgp->interpreter_name, td);
+		args->fname = imgp->interpreter_name;
 		goto interpret;
 	}
 
@@ -494,7 +529,7 @@
 	vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY, td);
 
 	/* Get a reference to the vnode prior to locking the proc */
-	VREF(ndp->ni_vp);
+	VREF(binvp);
 
 	/*
 	 * For security and other reasons, signal handlers cannot
@@ -520,8 +555,14 @@
 	execsigs(p);
 
 	/* name this process - nameiexec(p, ndp) */
-	len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN);
-	bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len);
+	/* XXX: what for fexecve? */
+	if (args->fname) {
+   		len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN);
+		bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len);
+	} else {
+	   	len = 10;
+	   	bcopy("fexec neco", p->p_comm, 10);
+	}
 	p->p_comm[len] = 0;
 
 	/*
@@ -650,7 +691,7 @@
 	 * to locking the proc lock.
 	 */
 	textvp = p->p_textvp;
-	p->p_textvp = ndp->ni_vp;
+	p->p_textvp = binvp;
 
 	/*
 	 * Notify others that we exec'd, and clear the P_INEXEC flag
@@ -733,8 +774,8 @@
 		vrele(textvp);
 		VFS_UNLOCK_GIANT(tvfslocked);
 	}
-	if (ndp->ni_vp && error != 0)
-		vrele(ndp->ni_vp);
+	if (binvp && error != 0)
+		vrele(binvp);
 #ifdef KTRACE
 	if (tracevp != NULL) {
 		int tvfslocked;
@@ -763,7 +804,8 @@
 		exec_unmap_first_page(imgp);
 
 	if (imgp->vp != NULL) {
-		NDFREE(ndp, NDF_ONLY_PNBUF);
+		if (args->fname)
+   			NDFREE(ndp, NDF_ONLY_PNBUF);
 		vput(imgp->vp);
 	}
 
@@ -981,11 +1023,14 @@
 	/*
 	 * Copy the file name.
 	 */
-	error = (segflg == UIO_SYSSPACE) ?
-	    copystr(fname, args->fname, PATH_MAX, &length) :
-	    copyinstr(fname, args->fname, PATH_MAX, &length);
-	if (error != 0)
-		goto err_exit;
+	if (fname != NULL) {
+		error = (segflg == UIO_SYSSPACE) ?
+		copystr(fname, args->fname, PATH_MAX, &length) :
+		copyinstr(fname, args->fname, PATH_MAX, &length);
+		if (error != 0)
+			goto err_exit;
+	} else
+		args->fname = NULL;
 
 	/*
 	 * extract arguments first
--- kern/syscalls.c.orig
+++ kern/syscalls.c
@@ -2,7 +2,7 @@
  * System call names.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/kern/syscalls.c,v 1.212 2006/11/11 22:01:25 ru Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.231 2006/11/03 15:23:14 rrs Exp 
  */
 
@@ -482,4 +482,19 @@
 	"sctp_generic_sendmsg",			/* 472 = sctp_generic_sendmsg */
 	"sctp_generic_sendmsg_iov",			/* 473 = sctp_generic_sendmsg_iov */
 	"sctp_generic_recvmsg",			/* 474 = sctp_generic_recvmsg */
+	"faccessat",			/* 475 = faccessat */
+	"fchmodat",			/* 476 = fchmodat */
+	"fchownat",			/* 477 = fchownat */
+	"fexecve",			/* 478 = fexecve */
+	"fstatat",			/* 479 = fstatat */
+	"futimesat",			/* 480 = futimesat */
+	"linkat",			/* 481 = linkat */
+	"mkdirat",			/* 482 = mkdirat */
+	"mkfifoat",			/* 483 = mkfifoat */
+	"mknodat",			/* 484 = mknodat */
+	"openat",			/* 485 = openat */
+	"readlinkat",			/* 486 = readlinkat */
+	"renameat",			/* 487 = renameat */
+	"symlinkat",			/* 488 = symlinkat */
+	"unlinkat",			/* 489 = unlinkat */
 };
--- kern/syscalls.master.orig
+++ kern/syscalls.master
@@ -835,5 +835,21 @@
 474     AUE_NULL        STD    { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
 				    struct sockaddr * from, __socklen_t *fromlenaddr, \
 				    struct sctp_sndrcvinfo *sinfo, int *msg_flags); }
+475	AUE_ACCESS	STD	{ int faccessat(int dirfd, char *path, int mode, int flag); }
+476	AUE_CHMOD	STD	{ int fchmodat(int dirfd, char *path, mode_t mode, int flag); }
+477	AUE_CHOWN	STD	{ int fchownat(int dirfd, char *path, uid_t uid, gid_t gid, int flag); }
+478	AUE_EXECVE	STD	{ int fexecve(int fd, char **argv, char **envv); }
+479	AUE_STAT	STD	{ int fstatat(int fd, char *path, struct stat *buf, int flag); }
+480	AUE_UTIMES	STD	{ int futimesat(int fd, char *path, struct timeval *times); }
+481	AUE_LINK	STD	{ int linkat(int fd1, char *path1, int fd2, char *path2, int flag); }
+482	AUE_MKDIR	STD	{ int mkdirat(int fd, char *path, mode_t mode); }
+483	AUE_MKFIFO	STD	{ int mkfifoat(int fd, char *path, mode_t mode); }
+484	AUE_MKNOD	STD	{ int mknodat(int fd, char *path, mode_t mode, dev_t dev); }
+; XXX: see the comment for open
+485	AUE_OPEN_RWTC	STD	{ int openat(int fd, char *path, int flag, mode_t mode); }
+486	AUE_READLINK	STD	{ ssize_t readlinkat(int fd, char *path, char *buf, size_t bufsize); }
+487	AUE_RENAME	STD	{ int renameat(int oldfd, char *old, int newfd, char *new); }
+488	AUE_SYMLINK	STD	{ int symlinkat(char *path1, int fd, char *path2); }
+489	AUE_UNLINK	STD	{ int unlinkat(int fd, char *path, int flag); }
 ; Please copy any additions and changes to the following compatability tables:
 ; sys/compat/freebsd32/syscalls.master
--- kern/systrace_args.c.orig
+++ kern/systrace_args.c
@@ -2,7 +2,7 @@
  * System call argument to DTrace register array converstion.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/kern/systrace_args.c,v 1.12 2006/11/11 22:01:25 ru Exp $
+ * $FreeBSD$
  * This file is part of the DTrace syscall provider.
  */
 
@@ -2805,6 +2805,152 @@
 		*n_args = 7;
 		break;
 	}
+	/* faccessat */
+	case 475: {
+		struct faccessat_args *p = params;
+		iarg[0] = p->dirfd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		iarg[2] = p->mode; /* int */
+		iarg[3] = p->flag; /* int */
+		*n_args = 4;
+		break;
+	}
+	/* fchmodat */
+	case 476: {
+		struct fchmodat_args *p = params;
+		iarg[0] = p->dirfd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		iarg[2] = p->mode; /* mode_t */
+		iarg[3] = p->flag; /* int */
+		*n_args = 4;
+		break;
+	}
+	/* fchownat */
+	case 477: {
+		struct fchownat_args *p = params;
+		iarg[0] = p->dirfd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		uarg[2] = p->uid; /* uid_t */
+		iarg[3] = p->gid; /* gid_t */
+		iarg[4] = p->flag; /* int */
+		*n_args = 5;
+		break;
+	}
+	/* fexecve */
+	case 478: {
+		struct fexecve_args *p = params;
+		iarg[0] = p->fd; /* int */
+		uarg[1] = (intptr_t) p->argv; /* char ** */
+		uarg[2] = (intptr_t) p->envv; /* char ** */
+		*n_args = 3;
+		break;
+	}
+	/* fstatat */
+	case 479: {
+		struct fstatat_args *p = params;
+		iarg[0] = p->fd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		uarg[2] = (intptr_t) p->buf; /* struct stat * */
+		iarg[3] = p->flag; /* int */
+		*n_args = 4;
+		break;
+	}
+	/* futimesat */
+	case 480: {
+		struct futimesat_args *p = params;
+		iarg[0] = p->fd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		uarg[2] = (intptr_t) p->times; /* struct timeval * */
+		*n_args = 3;
+		break;
+	}
+	/* linkat */
+	case 481: {
+		struct linkat_args *p = params;
+		iarg[0] = p->fd1; /* int */
+		uarg[1] = (intptr_t) p->path1; /* char * */
+		iarg[2] = p->fd2; /* int */
+		uarg[3] = (intptr_t) p->path2; /* char * */
+		iarg[4] = p->flag; /* int */
+		*n_args = 5;
+		break;
+	}
+	/* mkdirat */
+	case 482: {
+		struct mkdirat_args *p = params;
+		iarg[0] = p->fd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		iarg[2] = p->mode; /* mode_t */
+		*n_args = 3;
+		break;
+	}
+	/* mkfifoat */
+	case 483: {
+		struct mkfifoat_args *p = params;
+		iarg[0] = p->fd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		iarg[2] = p->mode; /* mode_t */
+		*n_args = 3;
+		break;
+	}
+	/* mknodat */
+	case 484: {
+		struct mknodat_args *p = params;
+		iarg[0] = p->fd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		iarg[2] = p->mode; /* mode_t */
+		iarg[3] = p->dev; /* dev_t */
+		*n_args = 4;
+		break;
+	}
+	/* openat */
+	case 485: {
+		struct openat_args *p = params;
+		iarg[0] = p->fd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		iarg[2] = p->flag; /* int */
+		iarg[3] = p->mode; /* mode_t */
+		*n_args = 4;
+		break;
+	}
+	/* readlinkat */
+	case 486: {
+		struct readlinkat_args *p = params;
+		iarg[0] = p->fd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		uarg[2] = (intptr_t) p->buf; /* char * */
+		uarg[3] = p->bufsize; /* size_t */
+		*n_args = 4;
+		break;
+	}
+	/* renameat */
+	case 487: {
+		struct renameat_args *p = params;
+		iarg[0] = p->oldfd; /* int */
+		uarg[1] = (intptr_t) p->old; /* char * */
+		iarg[2] = p->newfd; /* int */
+		uarg[3] = (intptr_t) p->new; /* char * */
+		*n_args = 4;
+		break;
+	}
+	/* symlinkat */
+	case 488: {
+		struct symlinkat_args *p = params;
+		uarg[0] = (intptr_t) p->path1; /* char * */
+		iarg[1] = p->fd; /* int */
+		uarg[2] = (intptr_t) p->path2; /* char * */
+		*n_args = 3;
+		break;
+	}
+	/* unlinkat */
+	case 489: {
+		struct unlinkat_args *p = params;
+		iarg[0] = p->fd; /* int */
+		uarg[1] = (intptr_t) p->path; /* char * */
+		iarg[2] = p->flag; /* int */
+		*n_args = 3;
+		break;
+	}
 	default:
 		*n_args = 0;
 		break;
--- kern/vfs_lookup.c.orig
+++ kern/vfs_lookup.c
@@ -44,6 +44,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/fcntl.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/namei.h>
@@ -192,7 +193,14 @@
 	ndp->ni_rootdir = fdp->fd_rdir;
 	ndp->ni_topdir = fdp->fd_jdir;
 
-	dp = fdp->fd_cdir;
+	if (ndp->ni_startdir)
+		dp = ndp->ni_startdir;
+	else {
+		dp = fdp->fd_cdir;
+		/* we might have raced so check it */
+		if ((cnp->cn_flags & ATBADF) && (cnp->cn_pnbuf[0] != '/'))
+			return (EBADF);
+	}
 	vfslocked = VFS_LOCK_GIANT(dp->v_mount);
 	VREF(dp);
 	FILEDESC_SUNLOCK(fdp);
@@ -1001,12 +1009,13 @@
  */
 int
 kern_alternate_path(struct thread *td, const char *prefix, char *path,
-    enum uio_seg pathseg, char **pathbuf, int create)
+    enum uio_seg pathseg, char **pathbuf, int create, int dirfd)
 {
 	struct nameidata nd, ndroot;
 	char *ptr, *buf, *cp;
 	size_t len, sz;
 	int error;
+	struct vnode *dir_vn;
 
 	buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
 	*pathbuf = buf;
@@ -1039,6 +1048,18 @@
 		goto keeporig;
 	}
 
+	if (dirfd == AT_FDCWD)
+		dir_vn = NULL;
+	else {
+	   	/* 
+		 * we want the original because the "prefix"
+		 * is included in the already opened dirfd
+		 */
+		bcopy(ptr, buf, len);
+		return (0);
+	}
+
+
 	/*
 	 * We know that there is a / somewhere in this pathname.
 	 * Search backwards for it, to find the file's parent dir
@@ -1051,13 +1072,13 @@
 		for (cp = &ptr[len] - 1; *cp != '/'; cp--);
 		*cp = '\0';
 
-		NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, buf, td);
+		NDINIT_AT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, buf, td, dir_vn);
 		error = namei(&nd);
 		*cp = '/';
 		if (error != 0)
 			goto keeporig;
 	} else {
-		NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, buf, td);
+		NDINIT_AT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, buf, td, dir_vn);
 
 		error = namei(&nd);
 		if (error != 0)
--- kern/vfs_syscalls.c.orig
+++ kern/vfs_syscalls.c
@@ -85,8 +85,10 @@
 static int setfflags(struct thread *td, struct vnode *, int);
 static int setutimes(struct thread *td, struct vnode *,
     const struct timespec *, int, int);
+static int kern_get_at(struct thread *td, int dirfd, struct vnode **dir_vn);
 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
     struct thread *td);
+static int kern_absolute_path(char *path, enum uio_seg pathseg);
 
 /*
  * The module initialization routine for POSIX asynchronous I/O will
@@ -953,10 +955,73 @@
 	return kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode);
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct openat_args {
+	int	fd;
+	char	*path;
+	int	flag;
+	int	mode;
+};
+#endif
 int
+openat(struct thread *td, struct openat_args *args)
+{
+	return kern_openat(td, args->path, UIO_USERSPACE, args->flag,
+	    args->mode, args->fd);
+}
+
+int
 kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags,
     int mode)
 {
+	return kern_openat(td, path, pathseg, flags, mode, AT_FDCWD);
+}
+
+static int
+kern_get_at(struct thread *td, int dirfd, struct vnode **dir_vn)
+{
+	int error;
+
+	if (dirfd == AT_FDCWD)
+		*dir_vn = NULL;
+	else {
+		error = fgetvp(td, dirfd, dir_vn);
+		if (error) {
+		   	*dir_vn = NULL;
+			return (error);
+		}
+		if ((*dir_vn)->v_type != VDIR) {
+			vrele(*dir_vn);
+			*dir_vn = NULL;
+			return (ENOTDIR);
+		}
+	}
+
+	return (0);
+}
+
+/* Check whether a path is an absolute path. */
+static int kern_absolute_path(char *path, enum uio_seg pathseg)
+{
+	int error;
+	char buf[1];
+
+	if (pathseg == UIO_SYSSPACE) {
+		return (path[0] == '/');		
+	} else {
+		error = copyin(path, buf, 1);
+		if (error)
+			return 0;	/* we want to fail */
+		return (buf[0] == '/');	
+	}
+}
+
+int
+kern_openat(struct thread *td, char *path, enum uio_seg pathseg, int flags,
+    int mode, int dirfd)
+{
+	struct nameidata nd;
+	struct vnode *dir_vn;
 	struct proc *p = td->td_proc;
 	struct filedesc *fdp = p->p_fd;
 	struct file *fp;
@@ -967,23 +1032,33 @@
 	struct file *nfp;
 	int type, indx, error;
 	struct flock lf;
-	struct nameidata nd;
 	int vfslocked;
 
 	AUDIT_ARG(fflags, flags);
 	AUDIT_ARG(mode, mode);
-	if ((flags & O_ACCMODE) == O_ACCMODE)
-		return (EINVAL);
+	/* XXX: audit dirfd */
+
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
+
+	NDINIT_AT(&nd, LOOKUP, ((error) ? ATBADF : 0) | FOLLOW | AUDITVNODE1 |
+	    MPSAFE, pathseg, path, td, dir_vn);
+
+	if ((flags & O_ACCMODE) == O_ACCMODE) {
+		error = EINVAL;
+		goto out;
+	}
 	flags = FFLAGS(flags);
+
 	error = falloc(td, &nfp, &indx);
 	if (error)
-		return (error);
+		goto out;
 	/* An extra reference on `nfp' has been held for us by falloc(). */
 	fp = nfp;
 	cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
-	NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg, path, td);
 	td->td_dupfd = -1;		/* XXX check for fdopen */
- 	error = vn_open(&nd, &flags, cmode, fp);
+	error = vn_open(&nd, &flags, cmode, fp);
 	if (error) {
 		/*
 		 * If the vn_open replaced the method vector, something
@@ -993,7 +1068,8 @@
 		if (error == ENXIO && fp->f_ops != &badfileops) {
 			fdrop(fp, td);
 			td->td_retval[0] = indx;
-			return (0);
+			error = 0;
+			goto out;
 		}
 
 		/*
@@ -1007,7 +1083,8 @@
 			dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
 			td->td_retval[0] = indx;
 			fdrop(fp, td);
-			return (0);
+			error = 0;
+			goto out;
 		}
 		/*
 		 * Clean up the descriptor, but only if another thread hadn't
@@ -1018,7 +1095,7 @@
 
 		if (error == ERESTART)
 			error = EINTR;
-		return (error);
+		goto out;
 	}
 	td->td_dupfd = 0;
 	vfslocked = NDHASGIANT(&nd);
@@ -1078,10 +1155,16 @@
 	fdrop(fp, td);
 	td->td_retval[0] = indx;
 	return (0);
+out:
+	if (dir_vn)
+		vrele(dir_vn);
+	return (error);
 bad:
 	VFS_UNLOCK_GIANT(vfslocked);
 	fdclose(fdp, fp, indx, td);
 	fdrop(fp, td);
+	if (dir_vn)
+		vrele(dir_vn);
 	return (error);
 }
 
@@ -1132,11 +1215,32 @@
 	return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev));
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct mknodat_args {
+	char	*path;
+	mode_t	mode;
+	dev_t	dev;
+};
+#endif
 int
+mknodat(struct thread *td, struct mknodat_args *args)
+{
+	return kern_mknodat(td, args->path, UIO_USERSPACE, args->mode,
+	    args->dev, args->fd);
+}
+
+int
 kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
     int dev)
 {
-	struct vnode *vp;
+	return kern_mknodat(td, path, pathseg, mode, dev, AT_FDCWD);
+}
+
+int
+kern_mknodat(struct thread *td, char *path, enum uio_seg pathseg, int mode,
+    int dev, int dirfd)
+{
+	struct vnode *vp, *dir_vn = NULL;
 	struct mount *mp;
 	struct vattr vattr;
 	int error;
@@ -1164,11 +1268,19 @@
 	if (error)
 		return (error);
 restart:
+	if (dir_vn)
+		vrele(dir_vn);
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
 	bwillwrite();
-	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
-	    pathseg, path, td);
-	if ((error = namei(&nd)) != 0)
+	NDINIT_AT(&nd, CREATE, ((error) ? ATBADF : 0) | LOCKPARENT |
+	    SAVENAME | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn);
+	if ((error = namei(&nd)) != 0) {
+		if (dir_vn)
+			vrele(dir_vn);
 		return (error);
+	}
 	vfslocked = NDHASGIANT(&nd);
 	vp = nd.ni_vp;
 	if (vp != NULL) {
@@ -1179,6 +1291,8 @@
 			vput(nd.ni_dvp);
 		vrele(vp);
 		VFS_UNLOCK_GIANT(vfslocked);
+		if (dir_vn)
+			vrele(dir_vn);
 		return (EEXIST);
 	} else {
 		VATTR_NULL(&vattr);
@@ -1210,8 +1324,11 @@
 		NDFREE(&nd, NDF_ONLY_PNBUF);
 		vput(nd.ni_dvp);
 		VFS_UNLOCK_GIANT(vfslocked);
-		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
+		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) {
+			if (dir_vn)
+				vrele(dir_vn);
 			return (error);
+		}
 		goto restart;
 	}
 #ifdef MAC
@@ -1230,6 +1347,8 @@
 				vput(nd.ni_vp);
 		}
 	}
+	if (dir_vn)
+		vrele(dir_vn);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vput(nd.ni_dvp);
 	vn_finished_write(mp);
@@ -1258,22 +1377,51 @@
 	return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode));
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct mkfifoat_args {
+	int	fd;
+	char	*path;
+	mode_t	mode;
+};
+#endif
+int
+mkfifoat(struct thread *td, struct mkfifoat_args *args)
+{
+	return kern_mkfifoat(td, args->path, UIO_USERSPACE, args->mode, args->fd);
+}
+
 int
 kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode)
 {
+	return kern_mkfifoat(td, path, pathseg, mode, AT_FDCWD);
+}
+
+int
+kern_mkfifoat(struct thread *td, char *path, enum uio_seg pathseg, int mode,
+    int dirfd)
+{
 	struct mount *mp;
 	struct vattr vattr;
 	int error;
 	struct nameidata nd;
 	int vfslocked;
+	struct vnode *dir_vn = NULL;
 
 	AUDIT_ARG(mode, mode);
 restart:
+	if (dir_vn)
+		vrele(dir_vn);
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
 	bwillwrite();
-	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
-	    pathseg, path, td);
-	if ((error = namei(&nd)) != 0)
+	NDINIT_AT(&nd, CREATE, ((error) ? ATBADF : 0) | LOCKPARENT |
+	    SAVENAME | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn);
+	if ((error = namei(&nd)) != 0) {
+		if (dir_vn)
+			vrele(dir_vn);
 		return (error);
+	}
 	vfslocked = NDHASGIANT(&nd);
 	if (nd.ni_vp != NULL) {
 		NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -1283,14 +1431,19 @@
 			vput(nd.ni_dvp);
 		vrele(nd.ni_vp);
 		VFS_UNLOCK_GIANT(vfslocked);
+		if (dir_vn)
+			vrele(dir_vn);
 		return (EEXIST);
 	}
 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
 		NDFREE(&nd, NDF_ONLY_PNBUF);
 		vput(nd.ni_dvp);
 		VFS_UNLOCK_GIANT(vfslocked);
-		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
+		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) {
+			if (dir_vn)
+				vrele(dir_vn);
 			return (error);
+	}
 		goto restart;
 	}
 	VATTR_NULL(&vattr);
@@ -1311,6 +1464,8 @@
 #ifdef MAC
 out:
 #endif
+	if (dir_vn)
+		vrele(dir_vn);
 	vput(nd.ni_dvp);
 	vn_finished_write(mp);
 	VFS_UNLOCK_GIANT(vfslocked);
@@ -1341,6 +1496,29 @@
 	return (error);
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct linkat_args {
+   	int	fd1;
+	char	*path1;
+	int	fd2;
+	char	*path2;
+	int	flag;
+};
+#endif
+int
+linkat(struct thread *td, struct linkat_args *args)
+{
+   	if (args->flag & ~AT_SYMLINK_FOLLOW)
+		return (EINVAL);
+
+	if (args->flag & AT_SYMLINK_FOLLOW)
+		return kern_linkat(td, args->path1, args->path2,
+		    UIO_USERSPACE, args->fd1, args->fd2, FOLLOW);
+	else
+		return kern_linkat(td, args->path1, args->path2,
+		    UIO_USERSPACE, args->fd1, args->fd2, 0);
+}
+
 static int hardlink_check_uid = 0;
 SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
     &hardlink_check_uid, 0,
@@ -1383,62 +1561,88 @@
 int
 kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
 {
+	return kern_linkat(td, path, link, segflg, AT_FDCWD, AT_FDCWD, FOLLOW);
+}
+
+int
+kern_linkat(struct thread *td, char *path, char *link, enum uio_seg segflg,
+    int olddirfd, int newdirfd, int follow)
+{
+	struct nameidata ndp, ndl;
+	int error;
+	struct vnode *pdir_vn, *ldir_vn;
 	struct vnode *vp;
 	struct mount *mp;
-	struct nameidata nd;
 	int vfslocked;
 	int lvfslocked;
-	int error;
+
+	error = kern_get_at(td, olddirfd, &pdir_vn);
+	if (error && !kern_absolute_path(path, segflg))
+		return (error);
+
+	NDINIT_AT(&ndp, LOOKUP, ((error) ? ATBADF : 0) | follow | MPSAFE |
+	    AUDITVNODE1, segflg, path, td, pdir_vn);
+
+	error = kern_get_at(td, newdirfd, &ldir_vn);
+	if (error && !kern_absolute_path(link, segflg))
+		return (error);
+
+	NDINIT_AT(&ndl, CREATE, ((error) ? ATBADF : 0) | LOCKPARENT |
+	    SAVENAME | MPSAFE | AUDITVNODE1, segflg, link, td, ldir_vn);
 
 	bwillwrite();
-	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, segflg, path, td);
-	if ((error = namei(&nd)) != 0)
-		return (error);
-	vfslocked = NDHASGIANT(&nd);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
-	vp = nd.ni_vp;
+	if ((error = namei(&ndp)) != 0)
+		goto out;
+	vfslocked = NDHASGIANT(&ndp);
+	NDFREE(&ndp, NDF_ONLY_PNBUF);
+	vp = ndp.ni_vp;
 	if (vp->v_type == VDIR) {
 		vrele(vp);
 		VFS_UNLOCK_GIANT(vfslocked);
-		return (EPERM);		/* POSIX */
+		error = EPERM;		/* POSIX */
+		goto out;
 	}
 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
 		vrele(vp);
 		VFS_UNLOCK_GIANT(vfslocked);
-		return (error);
+		goto out;
 	}
-	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE2,
-	    segflg, link, td);
-	if ((error = namei(&nd)) == 0) {
-		lvfslocked = NDHASGIANT(&nd);
-		if (nd.ni_vp != NULL) {
-			if (nd.ni_dvp == nd.ni_vp)
-				vrele(nd.ni_dvp);
+	if ((error = namei(&ndl)) == 0) {
+		lvfslocked = NDHASGIANT(&ndl);
+		if (ndl.ni_vp != NULL) {
+			if (ndl.ni_dvp == ndl.ni_vp)
+				vrele(ndl.ni_dvp);
 			else
-				vput(nd.ni_dvp);
-			vrele(nd.ni_vp);
+				vput(ndl.ni_dvp);
+			vrele(ndl.ni_vp);
 			error = EEXIST;
 		} else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td))
 		    == 0) {
-			VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
+			VOP_LEASE(ndl.ni_dvp, td, td->td_ucred, LEASE_WRITE);
 			VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
 			error = can_hardlink(vp, td, td->td_ucred);
 			if (error == 0)
 #ifdef MAC
 				error = mac_check_vnode_link(td->td_ucred,
-				    nd.ni_dvp, vp, &nd.ni_cnd);
+				    ndl.ni_dvp, vp, &ndl.ni_cnd);
 			if (error == 0)
 #endif
-				error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
+				error = VOP_LINK(ndl.ni_dvp, vp, &ndl.ni_cnd);
 			VOP_UNLOCK(vp, 0, td);
-			vput(nd.ni_dvp);
+			vput(ndl.ni_dvp);
 		}
-		NDFREE(&nd, NDF_ONLY_PNBUF);
+		NDFREE(&ndl, NDF_ONLY_PNBUF);
 		VFS_UNLOCK_GIANT(lvfslocked);
 	}
 	vrele(vp);
 	vn_finished_write(mp);
 	VFS_UNLOCK_GIANT(vfslocked);
+
+out:
+	if (pdir_vn)
+		vrele(pdir_vn);
+	if (ldir_vn)
+		vrele(ldir_vn);
 	return (error);
 }
 
@@ -1463,15 +1667,36 @@
 	return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE));
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct symlinkat_args {
+	char	*path;
+	int	fd;
+	char	*path2;
+};
+#endif
+int
+symlinkat(struct thread *td, struct symlinkat_args *args)
+{
+	return kern_symlinkat(td, args->path1, args->path2, UIO_USERSPACE, args->fd);
+}
+
 int
 kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg)
 {
+	return kern_symlinkat(td, path, link, segflg, AT_FDCWD);
+}
+
+int
+kern_symlinkat(struct thread *td, char *path, char *link, enum uio_seg segflg,
+    int dirfd)
+{
 	struct mount *mp;
 	struct vattr vattr;
 	char *syspath;
 	int error;
 	struct nameidata nd;
 	int vfslocked;
+	struct vnode *dir_vn = NULL;
 
 	if (segflg == UIO_SYSSPACE) {
 		syspath = path;
@@ -1482,9 +1707,14 @@
 	}
 	AUDIT_ARG(text, syspath);
 restart:
+	if (dir_vn)
+		vrele(dir_vn);
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(link, segflg))
+		return (error);
 	bwillwrite();
-	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
-	    segflg, link, td);
+	NDINIT_AT(&nd, CREATE, ((error) ? ATBADF : 0) | LOCKPARENT |
+	    SAVENAME | MPSAFE | AUDITVNODE1, segflg, link, td, dir_vn);
 	if ((error = namei(&nd)) != 0)
 		goto out;
 	vfslocked = NDHASGIANT(&nd);
@@ -1530,6 +1760,8 @@
 	vn_finished_write(mp);
 	VFS_UNLOCK_GIANT(vfslocked);
 out:
+	if (dir_vn)
+		vrele(dir_vn);
 	if (segflg != UIO_SYSSPACE)
 		uma_zfree(namei_zone, syspath);
 	return (error);
@@ -1608,21 +1840,54 @@
 	return (error);
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct unlinkat_args {
+	int	fd;
+	char	*path;
+	int	flag;
+};
+#endif
+int
+unlinkat(struct thread *td, struct unlinkat_args *args)
+{
+	if (args->flag & ~AT_REMOVEDIR)
+		return (EINVAL);
+
+	if (args->flag & AT_REMOVEDIR)
+		return kern_rmdirat(td, args->path, UIO_USERSPACE, args->fd);
+	else
+		return kern_unlinkat(td, args->path, UIO_USERSPACE, args->fd);
+}
+
 int
 kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
 {
+	return kern_unlinkat(td, path, pathseg, AT_FDCWD);
+}
+
+int
+kern_unlinkat(struct thread *td, char *path, enum uio_seg pathseg, int dirfd)
+{
 	struct mount *mp;
-	struct vnode *vp;
+	struct vnode *vp, *dir_vn = NULL;
 	int error;
 	struct nameidata nd;
 	int vfslocked;
-
+	
 restart:
+	if (dir_vn)
+		vrele(dir_vn);
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
 	bwillwrite();
-	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1,
-	    pathseg, path, td);
-	if ((error = namei(&nd)) != 0)
+	NDINIT_AT(&nd, DELETE, ((error) ? ATBADF : 0) | LOCKPARENT |
+	    LOCKLEAF | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn);
+	if ((error = namei(&nd)) != 0) {
+		if (dir_vn)
+			vrele(dir_vn);		
 		return (error == EINVAL ? EPERM : error);
+	}
 	vfslocked = NDHASGIANT(&nd);
 	vp = nd.ni_vp;
 	if (vp->v_type == VDIR)
@@ -1646,8 +1911,11 @@
 				vput(vp);
 			VFS_UNLOCK_GIANT(vfslocked);
 			if ((error = vn_start_write(NULL, &mp,
-			    V_XSLEEP | PCATCH)) != 0)
+			    V_XSLEEP | PCATCH)) != 0) {
+				if (dir_vn)
+					vrele(dir_vn);
 				return (error);
+			}
 			goto restart;
 		}
 #ifdef MAC
@@ -1665,6 +1933,8 @@
 	}
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vput(nd.ni_dvp);
+	if (dir_vn)
+		vrele(dir_vn);
 	if (vp == nd.ni_dvp)
 		vrele(vp);
 	else
@@ -1849,14 +2119,44 @@
 	return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags));
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct faccessat_args {
+	int	dirfd;
+	char	*path;
+	int	mode;
+	int	flag;
+}
+#endif
+int faccessat(struct thread *td, struct faccessat_args *args)
+{
+	if (args->flag & ~AT_EACCESS)
+		return (EINVAL);
+	/* XXX: what about mode? */
+	return kern_accessat(td, args->path, UIO_USERSPACE, args->flag, args->dirfd);
+}
+
 int
 kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags)
 {
+	return kern_accessat(td, path, pathseg, flags, AT_FDCWD);
+}
+
+int
+kern_accessat(struct thread *td, char *path, enum uio_seg pathseg, int flags, int dirfd)
+{
+	int error;
+	struct nameidata nd;
+	struct vnode *dir_vn;
 	struct ucred *cred, *tmpcred;
-	register struct vnode *vp;
-	struct nameidata nd;
+	struct vnode *vp;
 	int vfslocked;
-	int error;
+
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
+
+	NDINIT_AT(&nd, LOOKUP, ((error) ? ATBADF : 0) | FOLLOW | LOCKLEAF |
+	    MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn);
 
 	/*
 	 * Create and modify a temporary credential instead of one that
@@ -1865,13 +2165,16 @@
 	 */
 	cred = td->td_ucred;
 	tmpcred = crdup(cred);
-	tmpcred->cr_uid = cred->cr_ruid;
-	tmpcred->cr_groups[0] = cred->cr_rgid;
+	if (flags & AT_EACCESS) {
+		tmpcred->cr_uid = cred->cr_uid;
+		tmpcred->cr_groups[0] = cred->cr_groups[0];
+	} else {
+		tmpcred->cr_uid = cred->cr_ruid;
+		tmpcred->cr_groups[0] = cred->cr_rgid;
+	}
 	td->td_ucred = tmpcred;
-	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
-	    pathseg, path, td);
 	if ((error = namei(&nd)) != 0)
-		goto out1;
+		goto out;
 	vfslocked = NDHASGIANT(&nd);
 	vp = nd.ni_vp;
 
@@ -1879,9 +2182,11 @@
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vput(vp);
 	VFS_UNLOCK_GIANT(vfslocked);
-out1:
+out:
 	td->td_ucred = cred;
 	crfree(tmpcred);
+	if (dir_vn)
+		vrele(dir_vn);
 	return (error);
 }
 
@@ -2042,29 +2347,67 @@
 	return (error);
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct fstatat_args {
+	int	fd;
+	char	*path;
+	struct stat	*buf;
+	int	flag;
+}
+#endif
 int
+fstatat(struct thread *td, struct fstatat_args *args)
+{
+	if (args->flag & ~AT_SYMLINK_NOFOLLOW)
+		return (EINVAL);
+
+	if (args->flag & AT_SYMLINK_NOFOLLOW)
+		return kern_lstatat(td, args->path, UIO_USERSPACE, args->buf, args->fd);
+	else
+		return kern_statat(td, args->path, UIO_USERSPACE, args->buf, args->fd);
+}
+
+int
 kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
 {
+	return kern_statat(td, path, pathseg, sbp, AT_FDCWD);
+}
+
+int
+kern_statat(struct thread *td, char *path, enum uio_seg pathseg,
+    struct stat *sbp, int dirfd)
+{
 	struct nameidata nd;
+	struct vnode *dir_vn;
 	struct stat sb;
 	int error, vfslocked;
 
-	NDINIT(&nd, LOOKUP,
-	    FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | AUDITVNODE1,
-	    pathseg, path, td);
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
+
+	NDINIT_AT(&nd, LOOKUP, ((error) ? ATBADF : 0) | FOLLOW | LOCKSHARED |
+	    LOCKLEAF | AUDITVNODE1 | MPSAFE, pathseg, path, td, dir_vn);
+
 	if ((error = namei(&nd)) != 0)
-		return (error);
+		goto out;
 	vfslocked = NDHASGIANT(&nd);
 	error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vput(nd.ni_vp);
 	VFS_UNLOCK_GIANT(vfslocked);
+	/* dont bother with the path as this is hopefully going away soon */
 	if (mtx_owned(&Giant))
-		printf("stat(%d): %s\n", vfslocked, path);
+		printf("stat(%d):\n", vfslocked);
 	if (error)
-		return (error);
+		goto out;
 	*sbp = sb;
-	return (0);
+
+	error = 0;
+out:	
+	if (dir_vn)
+		vrele(dir_vn);
+	return (error);
 }
 
 /*
@@ -2096,16 +2439,28 @@
 int
 kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
 {
+	return kern_lstatat(td, path, pathseg, sbp, AT_FDCWD);
+}
+
+int
+kern_lstatat(struct thread *td, char *path, enum uio_seg pathseg,
+    struct stat *sbp, int dirfd)
+{
+	struct nameidata nd;
+	struct vnode *dir_vn;
 	struct vnode *vp;
 	struct stat sb;
-	struct nameidata nd;
 	int error, vfslocked;
 
-	NDINIT(&nd, LOOKUP,
-	    NOFOLLOW | LOCKLEAF | LOCKSHARED | MPSAFE | AUDITVNODE1,
-	    pathseg, path, td);
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
+
+	NDINIT_AT(&nd, LOOKUP, ((error) ? ATBADF : 0) | NOFOLLOW | LOCKLEAF |
+	    LOCKSHARED | AUDITVNODE1 | MPSAFE, pathseg, path, td, dir_vn);
+
 	if ((error = namei(&nd)) != 0)
-		return (error);
+		goto out;
 	vfslocked = NDHASGIANT(&nd);
 	vp = nd.ni_vp;
 	error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
@@ -2113,9 +2468,13 @@
 	vput(vp);
 	VFS_UNLOCK_GIANT(vfslocked);
 	if (error)
-		return (error);
+		goto out;
 	*sbp = sb;
-	return (0);
+	error = 0;
+out:	
+	if (dir_vn)
+		vrele(dir_vn);
+	return (error);
 }
 
 /*
@@ -2267,22 +2626,48 @@
 	return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf,
 	    UIO_USERSPACE, uap->count));
 }
+#ifndef _SYS_SYSPROTO_H_
+struct readlinkat_args {
+	int	fd;
+	char	*path;
+	char	*buf;
+	size_t	bufsize;
+};
+#endif
+ssize_t
+readlinkat(struct thread *td, struct readlinkat_args *args)
+{
+	return kern_readlinkat(td, args->path, UIO_USERSPACE,
+	    args->buf, UIO_USERSPACE, args->bufsize, args->fd);
+}
 
 int
 kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf,
     enum uio_seg bufseg, int count)
 {
-	register struct vnode *vp;
+	return kern_readlinkat(td, path, pathseg, buf, bufseg, count, AT_FDCWD);
+}
+
+int
+kern_readlinkat(struct thread *td, char *path, enum uio_seg pathseg, char *buf,
+    enum uio_seg bufseg, int count, int dirfd)
+{
+	struct nameidata nd;
+	struct vnode *dir_vn;
+	struct vnode *vp;
 	struct iovec aiov;
 	struct uio auio;
-	int error;
-	struct nameidata nd;
-	int vfslocked;
+	int error, vfslocked;
+
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
+
+	NDINIT_AT(&nd, LOOKUP, ((error) ? ATBADF : 0) | NOFOLLOW | LOCKLEAF |
+	    MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn);
 
-	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
-	    pathseg, path, td);
 	if ((error = namei(&nd)) != 0)
-		return (error);
+		goto out;
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vfslocked = NDHASGIANT(&nd);
 	vp = nd.ni_vp;
@@ -2291,7 +2676,7 @@
 	if (error) {
 		vput(vp);
 		VFS_UNLOCK_GIANT(vfslocked);
-		return (error);
+		goto out;
 	}
 #endif
 	if (vp->v_type != VLNK)
@@ -2311,6 +2696,9 @@
 	vput(vp);
 	VFS_UNLOCK_GIANT(vfslocked);
 	td->td_retval[0] = count - auio.uio_resid;
+out:
+	if (dir_vn)
+		vrele(dir_vn);
 	return (error);
 }
 
@@ -2455,6 +2843,7 @@
 }
 
 /*
+ *
  * Common implementation code for chmod(), lchmod() and fchmod().
  */
 static int
@@ -2504,22 +2893,59 @@
 	return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode));
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct fchmodat_args {
+	int	dirfd;
+	char	*path;
+	mode_t	mode;
+	int	flag;
+}
+#endif
+int
+fchmodat(struct thread *td, struct fchmodat_args *args)
+{
+	if (args->flag & ~AT_SYMLINK_NOFOLLOW)
+		return (EINVAL);
+
+	if (args->flag & AT_SYMLINK_NOFOLLOW)
+		return kern_lchmodat(td, args->path, UIO_USERSPACE,
+		    args->mode, args->dirfd);
+	else
+		return kern_chmodat(td, args->path, UIO_USERSPACE,
+		    args->mode, args->dirfd);
+}
+
 int
 kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode)
 {
-	int error;
+	return kern_chmodat(td, path, pathseg, mode, AT_FDCWD);
+}
+
+int
+kern_chmodat(struct thread *td, char *path, enum uio_seg pathseg,
+    mode_t mode, int dirfd)
+{
 	struct nameidata nd;
-	int vfslocked;
+	struct vnode *dir_vn;
+	int error, vfslocked;
+
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
+
+	NDINIT_AT(&nd, LOOKUP, ((error) ? ATBADF : 0) | FOLLOW | MPSAFE |
+	    AUDITVNODE1, pathseg, path, td, dir_vn);
 
-	AUDIT_ARG(mode, mode);
-	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
 	if ((error = namei(&nd)) != 0)
-		return (error);
+		goto out;
 	vfslocked = NDHASGIANT(&nd);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	error = setfmode(td, nd.ni_vp, mode);
 	vrele(nd.ni_vp);
 	VFS_UNLOCK_GIANT(vfslocked);
+out:	
+	if (dir_vn)
+		vrele(dir_vn);
 	return (error);
 }
 
@@ -2540,18 +2966,31 @@
 		int mode;
 	} */ *uap;
 {
+	return kern_lchmodat(td, uap->path, UIO_USERSPACE, uap->mode, AT_FDCWD);
+}
+
+
+int
+kern_lchmodat(struct thread *td, char *path, enum uio_seg pathseg,
+    mode_t mode, int dirfd)
+{
 	int error;
 	struct nameidata nd;
 	int vfslocked;
+	struct vnode *dir_vn;
 
-	AUDIT_ARG(mode, (mode_t)uap->mode);
-	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE,
-	    uap->path, td);
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
+
+	AUDIT_ARG(mode, mode);
+	NDINIT_AT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg,
+	    path, td, dir_vn);
 	if ((error = namei(&nd)) != 0)
 		return (error);
 	vfslocked = NDHASGIANT(&nd);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
-	error = setfmode(td, nd.ni_vp, uap->mode);
+	error = setfmode(td, nd.ni_vp, mode);
 	vrele(nd.ni_vp);
 	VFS_UNLOCK_GIANT(vfslocked);
 	return (error);
@@ -2649,23 +3088,54 @@
 	return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
 }
 
+#ifndef _SYS_SYSPROTO_H_
+#endif
+int
+fchownat(struct thread *td, struct fchownat_args *args)
+{
+	if (args->flag & ~AT_SYMLINK_NOFOLLOW)
+		return (EINVAL);
+
+	if (args->flag & AT_SYMLINK_NOFOLLOW)
+		return kern_lchownat(td, args->path, UIO_USERSPACE, args->uid,
+		    args->gid, args->dirfd);
+	else
+		return kern_chownat(td, args->path, UIO_USERSPACE, args->uid,
+		    args->gid, args->dirfd);
+}
+
 int
 kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
     int gid)
 {
-	int error;
+	return kern_chownat(td, path, pathseg, uid, gid, AT_FDCWD);
+}
+
+int
+kern_chownat(struct thread *td, char *path, enum uio_seg pathseg, int uid,
+    int gid, int dirfd)
+{
 	struct nameidata nd;
-	int vfslocked;
+	struct vnode *dir_vn;
+	int error, vfslocked;
+
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
+
+	NDINIT_AT(&nd, LOOKUP, ((error) ? ATBADF : 0) | FOLLOW | MPSAFE |
+	    AUDITVNODE1, pathseg, path, td, dir_vn);
 
-	AUDIT_ARG(owner, uid, gid);
-	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
 	if ((error = namei(&nd)) != 0)
-		return (error);
+		goto out;
 	vfslocked = NDHASGIANT(&nd);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	error = setfown(td, nd.ni_vp, uid, gid);
 	vrele(nd.ni_vp);
 	VFS_UNLOCK_GIANT(vfslocked);
+out:	
+	if (dir_vn)
+		vrele(dir_vn);
 	return (error);
 }
 
@@ -2696,19 +3166,34 @@
 kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
     int gid)
 {
-	int error;
+	return kern_lchownat(td, path, pathseg, uid, gid, AT_FDCWD);
+}
+
+int
+kern_lchownat(struct thread *td, char *path, enum uio_seg pathseg, int uid,
+    int gid, int dirfd)
+{
 	struct nameidata nd;
-	int vfslocked;
+	struct vnode *dir_vn;
+	int error, vfslocked;
+
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
+
+	NDINIT_AT(&nd, LOOKUP, ((error) ? ATBADF : 0) | NOFOLLOW | MPSAFE |
+	    AUDITVNODE1, pathseg, path, td, dir_vn);
 
-	AUDIT_ARG(owner, uid, gid);
-	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
 	if ((error = namei(&nd)) != 0)
-		return (error);
+		goto out;
 	vfslocked = NDHASGIANT(&nd);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	error = setfown(td, nd.ni_vp, uid, gid);
 	vrele(nd.ni_vp);
 	VFS_UNLOCK_GIANT(vfslocked);
+out:	
+	if (dir_vn)
+		vrele(dir_vn);
 	return (error);
 }
 
@@ -2851,25 +3336,49 @@
 	    UIO_USERSPACE));
 }
 
+#ifndef _SYS_SYSPROTO_H_
+#endif
+int
+futimesat(struct thread *td, struct futimesat_args *args)
+{
+	return kern_utimesat(td, args->path, UIO_USERSPACE, args->times, UIO_USERSPACE, args->fd);
+}
+
 int
 kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
     struct timeval *tptr, enum uio_seg tptrseg)
 {
+	return kern_utimesat(td, path, pathseg, tptr, tptrseg, AT_FDCWD);
+}
+
+int
+kern_utimesat(struct thread *td, char *path, enum uio_seg pathseg,
+    struct timeval *tptr, enum uio_seg tptrseg, int dirfd)
+{
+	struct nameidata nd;
+	struct vnode *dir_vn;
 	struct timespec ts[2];
-	int error;
-	struct nameidata nd;
-	int vfslocked;
+	int error, vfslocked;
+
+   	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
+
+	NDINIT_AT(&nd, LOOKUP, ((error) ? ATBADF : 0) | FOLLOW | AUDITVNODE1 |
+	    MPSAFE, pathseg, path, td, dir_vn);
 
 	if ((error = getutimes(tptr, tptrseg, ts)) != 0)
-		return (error);
-	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
+		goto out;
 	if ((error = namei(&nd)) != 0)
-		return (error);
+		goto out;
 	vfslocked = NDHASGIANT(&nd);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
 	vrele(nd.ni_vp);
 	VFS_UNLOCK_GIANT(vfslocked);
+out:
+	if (dir_vn)
+		vrele(dir_vn);
 	return (error);
 }
 
@@ -3217,26 +3726,60 @@
 	return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE));
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct renameat_args {
+	int	oldfd;
+	char	*old;
+	int	newfd;
+	char	*new;
+};
+#endif
 int
+renameat(struct thread *td, struct renameat_args *args)
+{
+	return kern_renameat(td, args->old, args->new, UIO_USERSPACE,
+	    args->oldfd, args->newfd);
+}
+
+int
 kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg)
 {
+	return kern_renameat(td, from, to, pathseg, AT_FDCWD, AT_FDCWD);
+}
+
+int
+kern_renameat(struct thread *td, char *from, char *to, enum uio_seg pathseg,
+    int fdirfd, int tdirfd)
+{
+	struct nameidata fromnd, tond;
+	struct vnode *fdir_vn, *tdir_vn;
 	struct mount *mp = NULL;
 	struct vnode *tvp, *fvp, *tdvp;
-	struct nameidata fromnd, tond;
 	int tvfslocked;
 	int fvfslocked;
 	int error;
 
-	bwillwrite();
+	error = kern_get_at(td, fdirfd, &fdir_vn);
+	if (error && !kern_absolute_path(from, pathseg))
+		return (error);
+	error = kern_get_at(td, tdirfd, &tdir_vn);
+	if (error && !kern_absolute_path(to, pathseg))
+		return (error);
+
 #ifdef MAC
-	NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE |
-	    AUDITVNODE1, pathseg, from, td);
+	NDINIT_AT(&fromnd, DELETE, ((error) ? ATBADF : 0) | LOCKPARENT |
+	    LOCKLEAF | SAVESTART | MPSAFE | AUDITVNODE1, pathseg, from, td, fdir_vn);
 #else
-	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE |
-	    AUDITVNODE1, pathseg, from, td);
+	NDINIT_AT(&fromnd, DELETE, ((error) ? ATBADF : 0) | WANTPARENT |
+	    SAVESTART | MPSAFE | AUDITVNODE1, pathseg, from, td, fdir_vn);
 #endif
+	NDINIT_AT(&tond, RENAME, ((error) ? ATBADF : 0) | LOCKPARENT |
+	    LOCKLEAF | NOCACHE | SAVESTART | MPSAFE | AUDITVNODE2,
+	    pathseg, to, td, tdir_vn);
+
+	bwillwrite();
 	if ((error = namei(&fromnd)) != 0)
-		return (error);
+		goto out2;
 	fvfslocked = NDHASGIANT(&fromnd);
 	tvfslocked = 0;
 #ifdef MAC
@@ -3255,8 +3798,6 @@
 		vrele(fvp);
 		goto out1;
 	}
-	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART |
-	    MPSAFE | AUDITVNODE2, pathseg, to, td);
 	if (fromnd.ni_vp->v_type == VDIR)
 		tond.ni_cnd.cn_flags |= WILLBEDIR;
 	if ((error = namei(&tond)) != 0) {
@@ -3328,6 +3869,12 @@
 	VFS_UNLOCK_GIANT(tvfslocked);
 	if (error == -1)
 		return (0);
+out2:
+	if (fdir_vn)
+		vrele(fdir_vn);
+	if (tdir_vn)
+		vrele(tdir_vn);
+
 	return (error);
 }
 
@@ -3352,11 +3899,30 @@
 	return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode));
 }
 
+#ifndef _SYS_SYSPROTO_H_
+struct mkdirat_args {
+	int	fd;
+	char	*path;
+	mode_t	mode;
+};
+#endif
+int
+mkdirat(struct thread *td, struct mkdirat_args *args)
+{
+	return kern_mkdirat(td, args->path, UIO_USERSPACE, args->mode, args->fd);
+}
+
 int
 kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode)
 {
+	return kern_mkdirat(td, path, segflg, mode, AT_FDCWD);
+}
+
+int
+kern_mkdirat(struct thread *td, char *path, enum uio_seg segflg, int mode, int dirfd)
+{
 	struct mount *mp;
-	struct vnode *vp;
+	struct vnode *vp, *dir_vn = NULL;
 	struct vattr vattr;
 	int error;
 	struct nameidata nd;
@@ -3364,12 +3930,20 @@
 
 	AUDIT_ARG(mode, mode);
 restart:
+	if (dir_vn)
+		vrele(dir_vn);
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, segflg))
+		return (error);
 	bwillwrite();
-	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
-	    segflg, path, td);
+	NDINIT_AT(&nd, CREATE, ((error) ? ATBADF : 0) | LOCKPARENT |
+	    SAVENAME | MPSAFE | AUDITVNODE1, segflg, path, td, dir_vn);
 	nd.ni_cnd.cn_flags |= WILLBEDIR;
-	if ((error = namei(&nd)) != 0)
+	if ((error = namei(&nd)) != 0) {
+		if (dir_vn)
+			vrele(dir_vn);
 		return (error);
+	}
 	vfslocked = NDHASGIANT(&nd);
 	vp = nd.ni_vp;
 	if (vp != NULL) {
@@ -3385,14 +3959,19 @@
 			vput(nd.ni_dvp);
 		vrele(vp);
 		VFS_UNLOCK_GIANT(vfslocked);
+		if (dir_vn)
+			vrele(dir_vn);
 		return (EEXIST);
 	}
 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
 		NDFREE(&nd, NDF_ONLY_PNBUF);
 		vput(nd.ni_dvp);
 		VFS_UNLOCK_GIANT(vfslocked);
-		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
+		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) {
+			if (dir_vn)
+				vrele(dir_vn);
 			return (error);
+		}
 		goto restart;
 	}
 	VATTR_NULL(&vattr);
@@ -3411,6 +3990,8 @@
 #ifdef MAC
 out:
 #endif
+	if (dir_vn)
+		vrele(dir_vn);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vput(nd.ni_dvp);
 	if (!error)
@@ -3442,16 +4023,25 @@
 int
 kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg)
 {
+	return kern_rmdirat(td, path, pathseg, AT_FDCWD);
+}
+
+int
+kern_rmdirat(struct thread *td, char *path, enum uio_seg pathseg, int dirfd)
+{
 	struct mount *mp;
-	struct vnode *vp;
+	struct vnode *vp, *dir_vn = NULL;
 	int error;
 	struct nameidata nd;
 	int vfslocked;
 
 restart:
+	error = kern_get_at(td, dirfd, &dir_vn);
+	if (error && !kern_absolute_path(path, pathseg))
+		return (error);
 	bwillwrite();
-	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1,
-	    pathseg, path, td);
+	NDINIT_AT(&nd, DELETE, ((error) ? ATBADF : 0) | LOCKPARENT |
+	    LOCKLEAF | MPSAFE | AUDITVNODE1, pathseg, path, td, dir_vn);
 	if ((error = namei(&nd)) != 0)
 		return (error);
 	vfslocked = NDHASGIANT(&nd);
--- modules/Makefile.orig
+++ modules/Makefile
@@ -413,7 +413,6 @@
 _tmpfs= 	tmpfs
 _wi=		wi
 _xe=		xe
-.if ${MK_ZFS} != "no" || defined(ALL_MODULES)
 _zfs=		zfs
 .endif
 .if ${MACHINE} == "i386"
@@ -462,7 +461,6 @@
 _pmc=		pmc
 _snc=		snc
 .endif
-.endif
 
 .if ${MACHINE_ARCH} == "amd64"
 _aac=		aac
--- sys/fcntl.h.orig
+++ sys/fcntl.h
@@ -74,6 +74,10 @@
 #define	O_WRONLY	0x0001		/* open for writing only */
 #define	O_RDWR		0x0002		/* open for reading and writing */
 #define	O_ACCMODE	0x0003		/* mask for above modes */
+#if 0
+#define	O_EXEC		0x0004		/* open for execute only */
+#define	O_ACCMODE	0x0007		/* mask for above modes */
+#endif
 
 /*
  * Kernel encoding of open mode; separate read and write bits that are
@@ -96,15 +100,22 @@
 #define	O_FSYNC		0x0080		/* synchronous writes */
 #endif
 #define	O_SYNC		0x0080		/* POSIX synonym for O_FSYNC */
-#if __BSD_VISIBLE
 #define	O_NOFOLLOW	0x0100		/* don't follow symlinks */
-#endif
 #define	O_CREAT		0x0200		/* create if nonexistent */
 #define	O_TRUNC		0x0400		/* truncate to zero length */
 #define	O_EXCL		0x0800		/* error if already exists */
 #ifdef _KERNEL
 #define	FHASLOCK	0x4000		/* descriptor holds advisory lock */
 #endif
+/* Defined by POSIX Extended API ... TODO: number of the spec */
+#define	AT_FDCWD		-100	/* Use the current working directory
+					   to determine the target of relative
+					   file paths.
+					 */
+#define	AT_EACCESS		0x100	/* Check access using effective user and group ID */
+#define	AT_SYMLINK_NOFOLLOW	0x200   /* Do not follow symbolic links */
+#define	AT_SYMLINK_FOLLOW	0x400	/* Follow symbolic link */
+#define	AT_REMOVEDIR		0x800	/* Remove directory instead of file */
 
 /* Defined by POSIX 1003.1; BSD default, but must be distinct from O_RDONLY. */
 #define	O_NOCTTY	0x8000		/* don't assign controlling terminal */
@@ -114,6 +125,9 @@
 #define O_DIRECT	0x00010000
 #endif
 
+/* Defined by POSIX Extended API ... TODO: number of the spec */
+#define	O_DIRECTORY	0x00020000	/* Fail if not directory */
+
 /*
  * XXX missing O_DSYNC, O_RSYNC.
  */
@@ -220,6 +234,7 @@
 int	open(const char *, int, ...);
 int	creat(const char *, mode_t);
 int	fcntl(int, int, ...);
+int	openat(int, const char *, int, ...);
 #if __BSD_VISIBLE
 int	flock(int, int);
 #endif
--- sys/imgact.h.orig
+++ sys/imgact.h
@@ -45,6 +45,7 @@
 	int stringspace;	/* space left in arg & env buffer */
 	int argc;		/* count of argument strings */
 	int envc;		/* count of environment strings */
+	int fd;			/* file descriptor of the executable */
 };
 
 struct image_params {
--- sys/namei.h.orig
+++ sys/namei.h
@@ -66,7 +66,10 @@
 	/*
 	 * Arguments to lookup.
 	 */
-	struct	vnode *ni_startdir;	/* starting directory */
+	struct	vnode *ni_startdir;	/* 
+					 * starting directory, also used for 
+					 * rename and *at functions 
+					 */
 	struct	vnode *ni_rootdir;	/* logical root directory */
 	struct	vnode *ni_topdir;	/* logical top directory */
 	/*
@@ -106,8 +109,9 @@
 #define	NOCACHE		0x0020	/* name must not be left in cache */
 #define	FOLLOW		0x0040	/* follow symbolic links */
 #define	LOCKSHARED	0x0100	/* Shared lock leaf */
+#define	ATBADF		0x0200	/* called from *at context with invalid dirfd */
 #define	NOFOLLOW	0x0000	/* do not follow symbolic links (pseudo) */
-#define	MODMASK		0x01fc	/* mask of operational modifiers */
+#define	MODMASK		0x03fc	/* mask of operational modifiers */
 /*
  * Namei parameter descriptors.
  *
@@ -148,20 +152,23 @@
 /*
  * Initialization of a nameidata structure.
  */
-static void NDINIT(struct nameidata *, u_long, u_long, enum uio_seg,
-	    const char *, struct thread *);
+#define	NDINIT(ndp, op, flags, segflg, namep, td)	\
+		NDINIT_AT(ndp, op, flags, segflg, namep, td, NULL)
+
 static __inline void
-NDINIT(struct nameidata *ndp,
+NDINIT_AT(struct nameidata *ndp,
 	u_long op, u_long flags,
 	enum uio_seg segflg,
 	const char *namep,
-	struct thread *td)
+	struct thread *td,
+	struct vnode *dvp)
 {
 	ndp->ni_cnd.cn_nameiop = op;
 	ndp->ni_cnd.cn_flags = flags;
 	ndp->ni_segflg = segflg;
 	ndp->ni_dirp = namep;
 	ndp->ni_cnd.cn_thread = td;
+	ndp->ni_startdir = dvp;
 }
 
 #define NDF_NO_DVP_RELE		0x00000001
--- sys/stat.h.orig
+++ sys/stat.h
@@ -338,6 +338,10 @@
 #endif
 int	stat(const char * __restrict, struct stat * __restrict);
 mode_t	umask(mode_t);
+int	fstatat(int, const char *, struct stat *, int);
+int	mkdirat(int, const char *, mode_t);
+int	mkfifoat(int, const char *, mode_t);
+int	mknodat(int, const char *, mode_t, dev_t);
 __END_DECLS
 #endif /* !_KERNEL */
 
--- sys/syscall.h.orig
+++ sys/syscall.h
@@ -2,7 +2,7 @@
  * System call numbers.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/sys/syscall.h,v 1.209 2006/11/11 22:01:24 ru Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.231 2006/11/03 15:23:14 rrs Exp 
  */
 
@@ -394,4 +394,19 @@
 #define	SYS_sctp_generic_sendmsg	472
 #define	SYS_sctp_generic_sendmsg_iov	473
 #define	SYS_sctp_generic_recvmsg	474
-#define	SYS_MAXSYSCALL	475
+#define	SYS_faccessat	475
+#define	SYS_fchmodat	476
+#define	SYS_fchownat	477
+#define	SYS_fexecve	478
+#define	SYS_fstatat	479
+#define	SYS_futimesat	480
+#define	SYS_linkat	481
+#define	SYS_mkdirat	482
+#define	SYS_mkfifoat	483
+#define	SYS_mknodat	484
+#define	SYS_openat	485
+#define	SYS_readlinkat	486
+#define	SYS_renameat	487
+#define	SYS_symlinkat	488
+#define	SYS_unlinkat	489
+#define	SYS_MAXSYSCALL	490
--- sys/syscall.mk.orig
+++ sys/syscall.mk
@@ -1,6 +1,6 @@
 # FreeBSD system call names.
 # DO NOT EDIT-- this file is automatically generated.
-# $FreeBSD: src/sys/sys/syscall.mk,v 1.164 2006/11/11 22:01:24 ru Exp $
+# $FreeBSD$
 # created from FreeBSD: src/sys/kern/syscalls.master,v 1.231 2006/11/03 15:23:14 rrs Exp 
 MIASM =  \
 	syscall.o \
@@ -335,4 +335,19 @@
 	sctp_peeloff.o \
 	sctp_generic_sendmsg.o \
 	sctp_generic_sendmsg_iov.o \
-	sctp_generic_recvmsg.o
+	sctp_generic_recvmsg.o \
+	faccessat.o \
+	fchmodat.o \
+	fchownat.o \
+	fexecve.o \
+	fstatat.o \
+	futimesat.o \
+	linkat.o \
+	mkdirat.o \
+	mkfifoat.o \
+	mknodat.o \
+	openat.o \
+	readlinkat.o \
+	renameat.o \
+	symlinkat.o \
+	unlinkat.o
--- sys/syscallsubr.h.orig
+++ sys/syscallsubr.h
@@ -56,16 +56,24 @@
 	    socklen_t *namelen, struct file **fp);
 int	kern_access(struct thread *td, char *path, enum uio_seg pathseg,
 	    int flags);
+int	kern_accessat(struct thread *td, char *path, enum uio_seg pathseg,
+	    int flags, int dirfd);
 int	kern_adjtime(struct thread *td, struct timeval *delta,
 	    struct timeval *olddelta);
 int	kern_alternate_path(struct thread *td, const char *prefix, char *path,
-	    enum uio_seg pathseg, char **pathbuf, int create);
+	    enum uio_seg pathseg, char **pathbuf, int create, int dirfd);
 int	kern_bind(struct thread *td, int fd, struct sockaddr *sa);
 int	kern_chdir(struct thread *td, char *path, enum uio_seg pathseg);
 int	kern_chmod(struct thread *td, char *path, enum uio_seg pathseg,
 	    int mode);
+int	kern_chmodat(struct thread *td, char *path, enum uio_seg pathseg,
+	    mode_t mode, int dirfd);
 int	kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
 	    int gid);
+int	kern_lchmodat(struct thread *td, char *path, enum uio_seg pathseg,
+	    mode_t mode, int dirfd);
+int	kern_chownat(struct thread *td, char *path, enum uio_seg pathseg, int uid,
+	    int gid, int dirfd);
 int	kern_clock_getres(struct thread *td, clockid_t clock_id,
 	    struct timespec *ts);
 int	kern_clock_gettime(struct thread *td, clockid_t clock_id,
@@ -102,18 +110,30 @@
 int	kern_kldunload(struct thread *td, int fileid, int flags);
 int	kern_lchown(struct thread *td, char *path, enum uio_seg pathseg,
 	    int uid, int gid);
+int	kern_lchownat(struct thread *td, char *path, enum uio_seg pathseg,
+	    int uid, int gid, int dirfd);
 int	kern_link(struct thread *td, char *path, char *link,
 	    enum uio_seg segflg);
+int	kern_linkat(struct thread *td, char *path, char *link,
+	    enum uio_seg segflg, int olddfd, int newdfd, int follow);
 int	kern_lstat(struct thread *td, char *path, enum uio_seg pathseg,
 	    struct stat *sbp);
+int	kern_lstatat(struct thread *td, char *path, enum uio_seg pathseg,
+	    struct stat *sbp, int dfd);
 int	kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg,
 	    struct timeval *tptr, enum uio_seg tptrseg);
 int	kern_mkdir(struct thread *td, char *path, enum uio_seg segflg,
 	    int mode);
+int	kern_mkdirat(struct thread *td, char *path, enum uio_seg segflg,
+	    int mode, int dirfd);
 int	kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg,
 	    int mode);
+int	kern_mkfifoat(struct thread *td, char *path, enum uio_seg pathseg,
+	    int mode, int dirfd);
 int	kern_mknod(struct thread *td, char *path, enum uio_seg pathseg,
 	    int mode, int dev);
+int	kern_mknodat(struct thread *td, char *path, enum uio_seg pathseg,
+	    int mode, int dev, int dirfd);
 int	kern_msgctl(struct thread *, int, int, struct msqid_ds *);
 int	kern_msgsnd(struct thread *, int, const void *, size_t, int, long);
 int	kern_msgrcv(struct thread *, int, void *, size_t, long, int, long *);
@@ -121,6 +141,8 @@
 	    struct timespec *rmt);
 int	kern_open(struct thread *td, char *path, enum uio_seg pathseg,
 	    int flags, int mode);
+int	kern_openat(struct thread *td, char *path, enum uio_seg pathseg,
+	    int flags, int mode, int dirfd);
 int	kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg,
 	    int name);
 int	kern_preadv(struct thread *td, int fd, struct uio *auio, off_t offset);
@@ -129,12 +151,17 @@
 int	kern_pwritev(struct thread *td, int fd, struct uio *auio, off_t offset);
 int	kern_readlink(struct thread *td, char *path, enum uio_seg pathseg,
 	    char *buf, enum uio_seg bufseg, int count);
+int	kern_readlinkat(struct thread *td, char *path, enum uio_seg pathseg,
+	    char *buf, enum uio_seg bufseg, int count, int dirfd);
 int	kern_readv(struct thread *td, int fd, struct uio *auio);
 int	kern_recvit(struct thread *td, int s, struct msghdr *mp,
 	    enum uio_seg fromseg, struct mbuf **controlp);
 int	kern_rename(struct thread *td, char *from, char *to,
 	    enum uio_seg pathseg);
+int	kern_renameat(struct thread *td, char *from, char *to,
+	    enum uio_seg pathseg, int fdirfd, int tdirfd);
 int	kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg);
+int	kern_rmdirat(struct thread *td, char *path, enum uio_seg pathseg, int dirfd);
 int	kern_sched_rr_get_interval(struct thread *td, pid_t pid,
 	    struct timespec *ts);
 int	kern_semctl(struct thread *td, int semid, int semnum, int cmd,
@@ -165,17 +192,24 @@
 int	kern_sigsuspend(struct thread *td, sigset_t mask);
 int	kern_stat(struct thread *td, char *path, enum uio_seg pathseg,
 	    struct stat *sbp);
+int	kern_statat(struct thread *td, char *path, enum uio_seg pathseg,
+	    struct stat *sbp, int dfd);
 int	kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
 	    struct statfs *buf);
 int	kern_symlink(struct thread *td, char *path, char *link,
 	    enum uio_seg segflg);
+int	kern_symlinkat(struct thread *td, char *path, char *link,
+	    enum uio_seg segflg, int dirfd);
 int	kern_thr_new(struct thread *td, struct thr_param *param);
 int	kern_thr_suspend(struct thread *td, struct timespec *tsp);
 int	kern_truncate(struct thread *td, char *path, enum uio_seg pathseg,
 	    off_t length);
 int	kern_unlink(struct thread *td, char *path, enum uio_seg pathseg);
+int	kern_unlinkat(struct thread *td, char *path, enum uio_seg pathseg, int dirfd);
 int	kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
 	    struct timeval *tptr, enum uio_seg tptrseg);
+int	kern_utimesat(struct thread *td, char *path, enum uio_seg pathseg,
+	    struct timeval *tptr, enum uio_seg tptrseg, int dirfd);
 int	kern_wait(struct thread *td, pid_t pid, int *status, int options,
 	    struct rusage *rup);
 int	kern_writev(struct thread *td, int fd, struct uio *auio);
--- sys/sysproto.h.orig
+++ sys/sysproto.h
@@ -2,7 +2,7 @@
  * System call prototypes.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/sys/sysproto.h,v 1.213 2006/11/11 22:01:24 ru Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.231 2006/11/03 15:23:14 rrs Exp 
  */
 
@@ -1482,6 +1482,92 @@
 	char sinfo_l_[PADL_(struct sctp_sndrcvinfo *)]; struct sctp_sndrcvinfo * sinfo; char sinfo_r_[PADR_(struct sctp_sndrcvinfo *)];
 	char msg_flags_l_[PADL_(int *)]; int * msg_flags; char msg_flags_r_[PADR_(int *)];
 };
+struct faccessat_args {
+	char dirfd_l_[PADL_(int)]; int dirfd; char dirfd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
+	char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
+};
+struct fchmodat_args {
+	char dirfd_l_[PADL_(int)]; int dirfd; char dirfd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)];
+	char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
+};
+struct fchownat_args {
+	char dirfd_l_[PADL_(int)]; int dirfd; char dirfd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char uid_l_[PADL_(uid_t)]; uid_t uid; char uid_r_[PADR_(uid_t)];
+	char gid_l_[PADL_(gid_t)]; gid_t gid; char gid_r_[PADR_(gid_t)];
+	char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
+};
+struct fexecve_args {
+	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+	char argv_l_[PADL_(char **)]; char ** argv; char argv_r_[PADR_(char **)];
+	char envv_l_[PADL_(char **)]; char ** envv; char envv_r_[PADR_(char **)];
+};
+struct fstatat_args {
+	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char buf_l_[PADL_(struct stat *)]; struct stat * buf; char buf_r_[PADR_(struct stat *)];
+	char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
+};
+struct futimesat_args {
+	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char times_l_[PADL_(struct timeval *)]; struct timeval * times; char times_r_[PADR_(struct timeval *)];
+};
+struct linkat_args {
+	char fd1_l_[PADL_(int)]; int fd1; char fd1_r_[PADR_(int)];
+	char path1_l_[PADL_(char *)]; char * path1; char path1_r_[PADR_(char *)];
+	char fd2_l_[PADL_(int)]; int fd2; char fd2_r_[PADR_(int)];
+	char path2_l_[PADL_(char *)]; char * path2; char path2_r_[PADR_(char *)];
+	char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
+};
+struct mkdirat_args {
+	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)];
+};
+struct mkfifoat_args {
+	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)];
+};
+struct mknodat_args {
+	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)];
+	char dev_l_[PADL_(dev_t)]; dev_t dev; char dev_r_[PADR_(dev_t)];
+};
+struct openat_args {
+	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
+	char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)];
+};
+struct readlinkat_args {
+	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
+	char bufsize_l_[PADL_(size_t)]; size_t bufsize; char bufsize_r_[PADR_(size_t)];
+};
+struct renameat_args {
+	char oldfd_l_[PADL_(int)]; int oldfd; char oldfd_r_[PADR_(int)];
+	char old_l_[PADL_(char *)]; char * old; char old_r_[PADR_(char *)];
+	char newfd_l_[PADL_(int)]; int newfd; char newfd_r_[PADR_(int)];
+	char new_l_[PADL_(char *)]; char * new; char new_r_[PADR_(char *)];
+};
+struct symlinkat_args {
+	char path1_l_[PADL_(char *)]; char * path1; char path1_r_[PADR_(char *)];
+	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+	char path2_l_[PADL_(char *)]; char * path2; char path2_r_[PADR_(char *)];
+};
+struct unlinkat_args {
+	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+	char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
+};
 int	nosys(struct thread *, struct nosys_args *);
 void	sys_exit(struct thread *, struct sys_exit_args *);
 int	fork(struct thread *, struct fork_args *);
@@ -1814,6 +1900,21 @@
 int	sctp_generic_sendmsg(struct thread *, struct sctp_generic_sendmsg_args *);
 int	sctp_generic_sendmsg_iov(struct thread *, struct sctp_generic_sendmsg_iov_args *);
 int	sctp_generic_recvmsg(struct thread *, struct sctp_generic_recvmsg_args *);
+int	faccessat(struct thread *, struct faccessat_args *);
+int	fchmodat(struct thread *, struct fchmodat_args *);
+int	fchownat(struct thread *, struct fchownat_args *);
+int	fexecve(struct thread *, struct fexecve_args *);
+int	fstatat(struct thread *, struct fstatat_args *);
+int	futimesat(struct thread *, struct futimesat_args *);
+int	linkat(struct thread *, struct linkat_args *);
+int	mkdirat(struct thread *, struct mkdirat_args *);
+int	mkfifoat(struct thread *, struct mkfifoat_args *);
+int	mknodat(struct thread *, struct mknodat_args *);
+int	openat(struct thread *, struct openat_args *);
+int	readlinkat(struct thread *, struct readlinkat_args *);
+int	renameat(struct thread *, struct renameat_args *);
+int	symlinkat(struct thread *, struct symlinkat_args *);
+int	unlinkat(struct thread *, struct unlinkat_args *);
 
 #ifdef COMPAT_43
 
@@ -2365,6 +2466,21 @@
 #define	SYS_AUE_sctp_generic_sendmsg	AUE_NULL
 #define	SYS_AUE_sctp_generic_sendmsg_iov	AUE_NULL
 #define	SYS_AUE_sctp_generic_recvmsg	AUE_NULL
+#define	SYS_AUE_faccessat	AUE_ACCESS
+#define	SYS_AUE_fchmodat	AUE_CHMOD
+#define	SYS_AUE_fchownat	AUE_CHOWN
+#define	SYS_AUE_fexecve	AUE_EXECVE
+#define	SYS_AUE_fstatat	AUE_STAT
+#define	SYS_AUE_futimesat	AUE_UTIMES
+#define	SYS_AUE_linkat	AUE_LINK
+#define	SYS_AUE_mkdirat	AUE_MKDIR
+#define	SYS_AUE_mkfifoat	AUE_MKFIFO
+#define	SYS_AUE_mknodat	AUE_MKNOD
+#define	SYS_AUE_openat	AUE_OPEN_RWTC
+#define	SYS_AUE_readlinkat	AUE_READLINK
+#define	SYS_AUE_renameat	AUE_RENAME
+#define	SYS_AUE_symlinkat	AUE_SYMLINK
+#define	SYS_AUE_unlinkat	AUE_UNLINK
 
 #undef PAD_
 #undef PADL_
--- sys/time.h.orig
+++ sys/time.h
@@ -320,6 +320,7 @@
 int	setitimer(int, const struct itimerval *, struct itimerval *);
 int	settimeofday(const struct timeval *, const struct timezone *);
 int	utimes(const char *, const struct timeval *);
+int	futimesat(int, const char *, const struct timeval [2]);
 __END_DECLS
 
 #endif /* !_KERNEL */
