--- ./fs/stat.c.firstwave	2010-01-25 14:52:25.000000000 +0300
+++ ./fs/stat.c	2010-01-25 19:30:44.000000000 +0300
@@ -161,12 +161,12 @@ int vfs_fstat(unsigned int fd, struct ks
 
 EXPORT_SYMBOL(vfs_fstat);
 
-int vfs_stat64(char __user *name, struct kstat64 *stat)
+static int vfs_stat64_fd(int dfd, char __user *name, struct kstat64 *stat)
 {
 	struct nameidata nd;
 	int error;
 
-	error = user_path_walk(name, &nd);
+	error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
 	if (!error) {
 		error = vfs_getattr64(nd.mnt, nd.dentry, stat);
 		path_release(&nd);
@@ -174,14 +174,18 @@ int vfs_stat64(char __user *name, struct
 	return error;
 }
 
+int vfs_stat64(char __user *name, struct kstat64 *stat)
+{
+	return vfs_stat64_fd(AT_FDCWD, name, stat);
+}
 EXPORT_SYMBOL(vfs_stat64);
 
-int vfs_lstat64(char __user *name, struct kstat64 *stat)
+static int vfs_lstat64_fd(int dfd, char __user *name, struct kstat64 *stat)
 {
 	struct nameidata nd;
 	int error;
 
-	error = user_path_walk_link(name, &nd);
+	error = __user_walk_fd(dfd, name, 0, &nd);
 	if (!error) {
 		error = vfs_getattr64(nd.mnt, nd.dentry, stat);
 		path_release(&nd);
@@ -189,6 +193,10 @@ int vfs_lstat64(char __user *name, struc
 	return error;
 }
 
+int vfs_lstat64(char __user *name, struct kstat64 *stat)
+{
+	return vfs_lstat64_fd(AT_FDCWD, name, stat);
+}
 EXPORT_SYMBOL(vfs_lstat64);
 
 int vfs_fstat64(unsigned int fd, struct kstat64 *stat)
@@ -341,6 +349,7 @@ asmlinkage long sys_newstat(char __user 
 
 	return error;
 }
+
 asmlinkage long sys_newlstat(char __user * filename, struct stat __user * statbuf)
 {
 	struct kstat64 stat;
@@ -351,6 +360,30 @@ asmlinkage long sys_newlstat(char __user
 
 	return error;
 }
+
+#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
+asmlinkage long sys_newfstatat(int dfd, char __user *filename,
+		struct stat __user *statbuf, int flag)
+{
+	struct kstat64 stat;
+	int error = -EINVAL;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	if (flag & AT_SYMLINK_NOFOLLOW)
+		error = vfs_lstat64_fd(dfd, filename, &stat);
+	else
+		error = vfs_stat64_fd(dfd, filename, &stat);
+
+	if (!error)
+		error = cp_new_stat(&stat, statbuf);
+
+out:
+	return error;
+}
+#endif
+
 asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf)
 {
 	struct kstat64 stat;
@@ -362,7 +395,8 @@ asmlinkage long sys_newfstat(unsigned in
 	return error;
 }
 
-asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bufsiz)
+asmlinkage long sys_readlinkat(int dfd, const char __user * path,
+		char __user * buf, int bufsiz)
 {
 	struct nameidata nd;
 	int error;
@@ -370,7 +404,7 @@ asmlinkage long sys_readlink(const char 
 	if (bufsiz <= 0)
 		return -EINVAL;
 
-	error = user_path_walk_link(path, &nd);
+	error = __user_walk_fd(dfd, path, 0, &nd);
 	if (!error) {
 		struct inode * inode = nd.dentry->d_inode;
 
@@ -387,6 +421,10 @@ asmlinkage long sys_readlink(const char 
 	return error;
 }
 
+asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bufsiz)
+{
+	return sys_readlinkat(AT_FDCWD, path, buf, bufsiz);
+}
 
 /* ---------- LFS-64 ----------- */
 #ifdef __ARCH_WANT_STAT64
@@ -457,6 +495,26 @@ asmlinkage long sys_fstat64(unsigned lon
 	return error;
 }
 
+asmlinkage long sys_fstatat64(int dfd, char __user *filename,
+		struct stat64 __user *statbuf, int flag)
+{
+	struct kstat64 stat;
+	int error = -EINVAL;
+
+	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+		goto out;
+
+	if (flag & AT_SYMLINK_NOFOLLOW)
+		error = vfs_lstat64_fd(dfd, filename, &stat);
+	else
+		error = vfs_stat64_fd(dfd, filename, &stat);
+
+	if (!error)
+		error = cp_new_stat64(&stat, statbuf);
+
+out:
+	return error;
+}
 #endif /* __ARCH_WANT_STAT64 */
 
 void inode_add_bytes(struct inode *inode, loff_t bytes)

