--- ./arch/x86_64/ia32/sys_ia32.c.firstwave	2010-01-25 14:52:25.000000000 +0300
+++ ./arch/x86_64/ia32/sys_ia32.c	2010-01-25 20:04:56.000000000 +0300
@@ -1312,26 +1312,13 @@ asmlinkage long sys32_io_getevents(aio_c
 
 asmlinkage long sys32_open(const char __user * filename, int flags, int mode)
 {
-	char * tmp;
-	int fd, error;
-
 	/* don't force O_LARGEFILE */
-	tmp = getname(filename);
-	fd = PTR_ERR(tmp);
-	if (!IS_ERR(tmp)) {
-		fd = get_unused_fd();
-		if (fd >= 0) {
-			struct file *f = filp_open(tmp, flags, mode);
-			error = PTR_ERR(f);
-			if (IS_ERR(f)) {
-				put_unused_fd(fd); 
-				fd = error;
-			} else
-				fd_install(fd, f);
-		}
-		putname(tmp);
-	}
-	return fd;
+	return do_sys_open(AT_FDCWD, filename, flags, mode);
+}
+
+asmlinkage long sys32_openat(int dfd, const char __user *filename, int flags, int mode)
+{
+	return do_sys_open(dfd, filename, flags, mode);
 }
 
 asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
--- ./fs/namei.c.firstwave	2010-01-25 14:52:25.000000000 +0300
+++ ./fs/namei.c	2010-01-25 19:50:22.000000000 +0300
@@ -1746,7 +1799,7 @@ int vfs_mknod(struct inode *dir, struct 
 	return error;
 }
 
-asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev)
+asmlinkage long sys_mknodat(int dfd, const char __user * filename, int mode, unsigned dev)
 {
 	int error = 0;
 	char * tmp;
@@ -1759,7 +1812,7 @@ asmlinkage long sys_mknod(const char __u
 	if (IS_ERR(tmp))
 		return PTR_ERR(tmp);
 
-	error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+	error = path_fd_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
 	if (error)
 		goto out;
 	dentry = lookup_create(&nd, 0);
@@ -1794,6 +1847,11 @@ out:
 
 	return error;
 }
+
+asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev)
+{
+	return sys_mknodat(AT_FDCWD, filename, mode, dev);
+}
 EXPORT_SYMBOL(sys_mknod);
 
 int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
@@ -1821,7 +1879,7 @@ int vfs_mkdir(struct inode *dir, struct 
 	return error;
 }
 
-asmlinkage long sys_mkdir(const char __user * pathname, int mode)
+asmlinkage long sys_mkdirat(int dfd, const char __user * pathname, int mode)
 {
 	int error = 0;
 	char * tmp;
@@ -1832,7 +1890,7 @@ asmlinkage long sys_mkdir(const char __u
 		struct dentry *dentry;
 		struct nameidata nd;
 
-		error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+		error = path_fd_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
 		if (error)
 			goto out;
 		dentry = lookup_create(&nd, 1);
@@ -1851,6 +1909,11 @@ out:
 
 	return error;
 }
+
+asmlinkage long sys_mkdir(const char __user * pathname, int mode)
+{
+	return sys_mkdirat(AT_FDCWD, pathname, mode);
+}
 EXPORT_SYMBOL(sys_mkdir);
 
 /*
@@ -1915,7 +1978,7 @@ int vfs_rmdir(struct inode *dir, struct 
 	return error;
 }
 
-asmlinkage long sys_rmdir(const char __user * pathname)
+static long do_rmdir(int dfd, const char __user * pathname)
 {
 	int error = 0;
 	char * name;
@@ -1926,7 +1989,7 @@ asmlinkage long sys_rmdir(const char __u
 	if(IS_ERR(name))
 		return PTR_ERR(name);
 
-	error = path_lookup(name, LOOKUP_PARENT, &nd);
+	error = path_fd_lookup(dfd, name, LOOKUP_PARENT, &nd);
 	if (error)
 		goto exit;
 
@@ -1955,6 +2018,11 @@ exit:
 	putname(name);
 	return error;
 }
+
+asmlinkage long sys_rmdir(const char __user * pathname)
+{
+	return do_rmdir(AT_FDCWD, pathname);
+}
 EXPORT_SYMBOL(sys_rmdir);
 
 int vfs_unlink(struct inode *dir, struct dentry *dentry)
@@ -1993,7 +2061,7 @@ int vfs_unlink(struct inode *dir, struct
  * writeout happening, and we don't want to prevent access to the directory
  * while waiting on the I/O.
  */
-asmlinkage long sys_unlink(const char __user * pathname)
+static long do_unlink(int dfd, const char __user * pathname)
 {
 	int error = 0;
 	char * name;
@@ -2005,7 +2073,7 @@ asmlinkage long sys_unlink(const char __
 	if(IS_ERR(name))
 		return PTR_ERR(name);
 
-	error = path_lookup(name, LOOKUP_PARENT, &nd);
+	error = path_fd_lookup(dfd, name, LOOKUP_PARENT, &nd);
 	if (error)
 		goto exit;
 	error = -EISDIR;
@@ -2039,6 +2107,24 @@ slashes:
 		S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR;
 	goto exit2;
 }
+
+asmlinkage long sys_unlinkat(int dfd, const char __user *pathname, int flag)
+{
+	if ((flag & ~AT_REMOVEDIR) != 0)
+		return -EINVAL;
+
+	if (flag & AT_REMOVEDIR)
+		return do_rmdir(dfd, pathname);
+
+	return do_unlink(dfd, pathname);
+
+}
+
+asmlinkage long sys_unlink(const char __user * pathname)
+{
+	return do_unlink(AT_FDCWD, pathname);
+}
+
 EXPORT_SYMBOL(sys_unlink);
 
 int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode)
@@ -2065,7 +2151,8 @@ int vfs_symlink(struct inode *dir, struc
 	return error;
 }
 
-asmlinkage long sys_symlink(const char __user * oldname, const char __user * newname)
+asmlinkage long sys_symlinkat(const char __user * oldname,
+		int newdfd, const char __user * newname)
 {
 	int error = 0;
 	char * from;
@@ -2080,7 +2167,7 @@ asmlinkage long sys_symlink(const char _
 		struct dentry *dentry;
 		struct nameidata nd;
 
-		error = path_lookup(to, LOOKUP_PARENT, &nd);
+		error = path_fd_lookup(newdfd, to, LOOKUP_PARENT, &nd);
 		if (error)
 			goto out;
 		dentry = lookup_create(&nd, 0);
@@ -2097,6 +2184,11 @@ out:
 	putname(from);
 	return error;
 }
+
+asmlinkage long sys_symlink(const char __user * oldname, const char __user * newname)
+{
+	return sys_symlinkat(oldname, AT_FDCWD, newname);
+}
 EXPORT_SYMBOL(sys_symlink);
 
 int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
@@ -2149,21 +2241,27 @@ int vfs_link(struct dentry *old_dentry, 
  * with linux 2.0, and to avoid hard-linking to directories
  * and other special files.  --ADM
  */
-asmlinkage long sys_link(const char __user * oldname, const char __user * newname)
+asmlinkage long sys_linkat(int olddfd, const char __user * oldname,
+		int newdfd, const char __user * newname, int flags)
 {
 	struct dentry *new_dentry;
 	struct nameidata nd, old_nd;
 	int error;
 	char * to;
 
+	if ((flags & ~AT_SYMLINK_FOLLOW) != 0)
+		return -EINVAL;
+
 	to = getname(newname);
 	if (IS_ERR(to))
 		return PTR_ERR(to);
 
-	error = __user_walk(oldname, 0, &old_nd);
+	error = __user_walk_fd(olddfd, oldname,
+			(flags & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0,
+			&old_nd);
 	if (error)
 		goto exit;
-	error = path_lookup(to, LOOKUP_PARENT, &nd);
+	error = path_fd_lookup(newdfd, to, LOOKUP_PARENT, &nd);
 	if (error)
 		goto out;
 	error = -EXDEV;
@@ -2186,6 +2284,10 @@ exit:
 	return error;
 }
 
+asmlinkage long sys_link(const char __user * oldname, const char __user * newname)
+{
+	return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
+}
 /*
  * The worst of all namespace operations - renaming directory. "Perverted"
  * doesn't even start to describe it. Somebody in UCB had a heck of a trip...
@@ -2339,7 +2441,7 @@ int vfs_rename(struct inode *old_dir, st
 	return error;
 }
 
-static inline int do_rename(const char * oldname, const char * newname)
+static inline int do_rename(int olddfd, const char * oldname, int newdfd, const char * newname)
 {
 	int error = 0;
 	struct dentry * old_dir, * new_dir;
@@ -2347,11 +2449,11 @@ static inline int do_rename(const char *
 	struct dentry * trap;
 	struct nameidata oldnd, newnd;
 
-	error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
+	error = path_fd_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd);
 	if (error)
 		goto exit;
 
-	error = path_lookup(newname, LOOKUP_PARENT, &newnd);
+	error = path_fd_lookup(newdfd, newname, LOOKUP_PARENT, &newnd);
 	if (error)
 		goto exit1;
 
@@ -2415,7 +2517,8 @@ exit:
 	return error;
 }
 
-asmlinkage long sys_rename(const char __user * oldname, const char __user * newname)
+asmlinkage long sys_renameat(int olddfd, const char __user * oldname,
+		int newdfd, const char __user * newname)
 {
 	int error;
 	char * from;
@@ -2427,12 +2530,17 @@ asmlinkage long sys_rename(const char __
 	to = getname(newname);
 	error = PTR_ERR(to);
 	if (!IS_ERR(to)) {
-		error = do_rename(from,to);
+		error = do_rename(olddfd, from, newdfd, to);
 		putname(to);
 	}
 	putname(from);
 	return error;
 }
+
+asmlinkage long sys_rename(const char __user * oldname, const char __user * newname)
+{
+	return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname);
+}
 EXPORT_SYMBOL(sys_rename);
 
 int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link)
--- ./fs/open.c.firstwave	2010-01-25 16:21:29.000000000 +0300
+++ ./fs/open.c	2010-01-25 20:18:51.000000000 +0300
@@ -499,7 +504,7 @@ asmlinkage long sys_utimes(char __user *
  * We do this by temporarily clearing all FS-related capabilities and
  * switching the fsuid/fsgid around to the real ones.
  */
-asmlinkage long sys_access(const char __user * filename, int mode)
+asmlinkage long sys_faccessat(int dfd, const char __user * filename, int mode)
 {
 	struct nameidata nd;
 	int old_fsuid, old_fsgid;
@@ -529,7 +534,7 @@ asmlinkage long sys_access(const char __
 	else
 		current->cap_effective = current->cap_permitted;
 
-	res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
+	res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
 	if (!res) {
 		res = permission(nd.dentry->d_inode, mode, &nd, NULL);
 		/* SuS v2 requires we report a read only fs too */
@@ -546,6 +551,11 @@ asmlinkage long sys_access(const char __
 	return res;
 }
 
+asmlinkage long sys_access(const char __user * filename, int mode)
+{
+	return sys_faccessat(AT_FDCWD, filename, mode);
+}
+
 asmlinkage long sys_chdir(const char __user * filename)
 {
 	struct nameidata nd;
@@ -662,14 +672,14 @@ out:
 	return err;
 }
 
-asmlinkage long sys_chmod(const char __user * filename, mode_t mode)
+static long do_chmod(int dfd, const char __user * filename, mode_t mode)
 {
 	struct nameidata nd;
 	struct inode * inode;
 	int error;
 	struct iattr newattrs;
 
-	error = user_path_walk(filename, &nd);
+	error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
 	if (error)
 		goto out;
 	inode = nd.dentry->d_inode;
@@ -696,6 +706,16 @@ out:
 	return error;
 }
 
+asmlinkage long sys_fchmodat(int dfd, const char __user * filename, mode_t mode)
+{
+	return do_chmod(dfd, filename, mode);
+}
+
+asmlinkage long sys_chmod(const char __user * filename, mode_t mode)
+{
+	return do_chmod(AT_FDCWD, filename, mode);
+}
+
 static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
 {
 	struct inode * inode;
@@ -731,6 +751,26 @@ out:
 	return error;
 }
 
+asmlinkage long sys_fchownat(int dfd, const char __user * filename,
+		uid_t user, gid_t group, int flag)
+{
+	struct nameidata nd;
+	int error = -EINVAL;
+	int follow;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
+	error = __user_walk_fd(dfd, filename, follow, &nd);
+	if (!error) {
+		error = chown_common(nd.dentry, user, group);
+		path_release(&nd);
+	}
+out:
+	return error;
+}
+
 asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
 {
 	struct nameidata nd;
@@ -788,7 +828,7 @@ static struct file *__dentry_open(struct
  * for the internal routines (ie open_namei()/follow_link() etc). 00 is
  * used by symlinks.
  */
-struct file *filp_open(const char * filename, int flags, int mode)
+static struct file *filp_fd_open(int dfd, const char * filename, int flags, int mode)
 {
 	int namei_flags, error;
 	struct nameidata nd;
@@ -803,7 +843,7 @@ struct file *filp_open(const char * file
 	if (f == NULL)
 		return ERR_PTR(error);
 
-	error = open_namei(filename, namei_flags, mode, &nd);
+	error = open_fd_namei(dfd, filename, namei_flags, mode, &nd);
 	if (!error)
 		return __dentry_open(nd.dentry, nd.mnt, flags, f);
 
@@ -811,6 +851,10 @@ struct file *filp_open(const char * file
 	return ERR_PTR(error);
 }
 
+struct file *filp_open(const char * filename, int flags, int mode)
+{
+	return filp_fd_open(AT_FDCWD, filename, flags, mode);
+}
 EXPORT_SYMBOL(filp_open);
 
 struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
@@ -994,20 +1038,17 @@ void fastcall fd_install(unsigned int fd
 
 EXPORT_SYMBOL(fd_install);
 
-asmlinkage long sys_open(const char __user * filename, int flags, int mode)
+long do_sys_open(int dfd, const char __user * filename, int flags, int mode)
 {
 	char * tmp;
 	int fd, error;
 
-	if (force_o_largefile())
-		flags |= O_LARGEFILE;
-
 	tmp = getname(filename);
 	fd = PTR_ERR(tmp);
 	if (!IS_ERR(tmp)) {
 		fd = get_unused_fd();
 		if (fd >= 0) {
-			struct file *f = filp_open(tmp, flags, mode);
+			struct file *f = filp_fd_open(dfd, tmp, flags, mode);
 			error = PTR_ERR(f);
 			if (IS_ERR(f))
 				goto out_error;
@@ -1024,6 +1065,30 @@ out_error:
 	goto out;
 }
 
+asmlinkage long sys_openat(int dfd, const char __user * filename, int flags, int mode)
+{
+	long ret;
+
+	if (force_o_largefile())
+		flags |= O_LARGEFILE;
+
+	ret = do_sys_open(dfd, filename, flags, mode);
+	prevent_tail_call(ret);
+	return ret;
+
+}
+
+asmlinkage long sys_open(const char __user * filename, int flags, int mode)
+{
+	long ret;
+
+	if (force_o_largefile())
+		flags |= O_LARGEFILE;
+
+	ret = do_sys_open(AT_FDCWD, filename, flags, mode);
+	prevent_tail_call(ret);
+	return ret;
+}
 #ifndef __alpha__
 
 /*
--- ./include/linux/fs.h.firstwave	2010-01-25 14:52:26.000000000 +0300
+++ ./include/linux/fs.h	2010-01-25 20:03:02.000000000 +0300
@@ -1324,6 +1324,7 @@ static inline int break_lease(struct ino
 /* fs/open.c */
 
 extern int do_truncate(struct dentry *, loff_t start, unsigned int);
+extern long do_sys_open(int dfd, const char __user * filename, int flags, int mode);
 extern struct file *filp_open(const char *, int, int);
 extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
 extern int filp_close(struct file *, fl_owner_t id);
