#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/security.h>
+#include <linux/syscalls.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
EXPORT_SYMBOL(vfs_getattr);
-int vfs_stat(char __user *name, struct kstat *stat)
+int vfs_stat_fd(int dfd, char __user *name, struct kstat *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_getattr(nd.mnt, nd.dentry, stat);
path_release(&nd);
return error;
}
+int vfs_stat(char __user *name, struct kstat *stat)
+{
+ return vfs_stat_fd(AT_FDCWD, name, stat);
+}
+
EXPORT_SYMBOL(vfs_stat);
-int vfs_lstat(char __user *name, struct kstat *stat)
+int vfs_lstat_fd(int dfd, char __user *name, struct kstat *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_getattr(nd.mnt, nd.dentry, stat);
path_release(&nd);
return error;
}
+int vfs_lstat(char __user *name, struct kstat *stat)
+{
+ return vfs_lstat_fd(AT_FDCWD, name, stat);
+}
+
EXPORT_SYMBOL(vfs_lstat);
int vfs_fstat(unsigned int fd, struct kstat *stat)
asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf)
{
struct kstat stat;
- int error = vfs_stat(filename, &stat);
+ int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
if (!error)
error = cp_old_stat(&stat, statbuf);
asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf)
{
struct kstat stat;
- int error = vfs_lstat(filename, &stat);
+ int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
if (!error)
error = cp_old_stat(&stat, statbuf);
return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}
-asmlinkage long sys_newstat(char __user * filename, struct stat __user * statbuf)
+asmlinkage long sys_newstat(char __user *filename, struct stat __user *statbuf)
{
struct kstat stat;
- int error = vfs_stat(filename, &stat);
+ int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
if (!error)
error = cp_new_stat(&stat, statbuf);
return error;
}
-asmlinkage long sys_newlstat(char __user * filename, struct stat __user * statbuf)
+
+asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
{
struct kstat stat;
- int error = vfs_lstat(filename, &stat);
+ int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
if (!error)
error = cp_new_stat(&stat, statbuf);
return error;
}
-asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf)
+
+#ifndef __ARCH_WANT_STAT64
+asmlinkage long sys_newfstatat(int dfd, char __user *filename,
+ struct stat __user *statbuf, int flag)
+{
+ struct kstat stat;
+ int error = -EINVAL;
+
+ if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+ goto out;
+
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ error = vfs_lstat_fd(dfd, filename, &stat);
+ else
+ error = vfs_stat_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 kstat stat;
int error = vfs_fstat(fd, &stat);
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;
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;
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
return error;
}
+asmlinkage long sys_fstatat64(int dfd, char __user *filename,
+ struct stat64 __user *statbuf, int flag)
+{
+ struct kstat stat;
+ int error = -EINVAL;
+
+ if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+ goto out;
+
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ error = vfs_lstat_fd(dfd, filename, &stat);
+ else
+ error = vfs_stat_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)