diff options
Diffstat (limited to 'fs/stat.c')
| -rw-r--r-- | fs/stat.c | 66 |
1 files changed, 53 insertions, 13 deletions
| @@ -63,12 +63,12 @@ int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
| 63 | 63 | ||
| 64 | EXPORT_SYMBOL(vfs_getattr); | 64 | EXPORT_SYMBOL(vfs_getattr); |
| 65 | 65 | ||
| 66 | int vfs_stat(char __user *name, struct kstat *stat) | 66 | int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat) |
| 67 | { | 67 | { |
| 68 | struct nameidata nd; | 68 | struct nameidata nd; |
| 69 | int error; | 69 | int error; |
| 70 | 70 | ||
| 71 | error = user_path_walk(name, &nd); | 71 | error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd); |
| 72 | if (!error) { | 72 | if (!error) { |
| 73 | error = vfs_getattr(nd.mnt, nd.dentry, stat); | 73 | error = vfs_getattr(nd.mnt, nd.dentry, stat); |
| 74 | path_release(&nd); | 74 | path_release(&nd); |
| @@ -76,14 +76,19 @@ int vfs_stat(char __user *name, struct kstat *stat) | |||
| 76 | return error; | 76 | return error; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | int vfs_stat(char __user *name, struct kstat *stat) | ||
| 80 | { | ||
| 81 | return vfs_stat_fd(AT_FDCWD, name, stat); | ||
| 82 | } | ||
| 83 | |||
| 79 | EXPORT_SYMBOL(vfs_stat); | 84 | EXPORT_SYMBOL(vfs_stat); |
| 80 | 85 | ||
| 81 | int vfs_lstat(char __user *name, struct kstat *stat) | 86 | int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat) |
| 82 | { | 87 | { |
| 83 | struct nameidata nd; | 88 | struct nameidata nd; |
| 84 | int error; | 89 | int error; |
| 85 | 90 | ||
| 86 | error = user_path_walk_link(name, &nd); | 91 | error = __user_walk_fd(dfd, name, 0, &nd); |
| 87 | if (!error) { | 92 | if (!error) { |
| 88 | error = vfs_getattr(nd.mnt, nd.dentry, stat); | 93 | error = vfs_getattr(nd.mnt, nd.dentry, stat); |
| 89 | path_release(&nd); | 94 | path_release(&nd); |
| @@ -91,6 +96,11 @@ int vfs_lstat(char __user *name, struct kstat *stat) | |||
| 91 | return error; | 96 | return error; |
| 92 | } | 97 | } |
| 93 | 98 | ||
| 99 | int vfs_lstat(char __user *name, struct kstat *stat) | ||
| 100 | { | ||
| 101 | return vfs_lstat_fd(AT_FDCWD, name, stat); | ||
| 102 | } | ||
| 103 | |||
| 94 | EXPORT_SYMBOL(vfs_lstat); | 104 | EXPORT_SYMBOL(vfs_lstat); |
| 95 | 105 | ||
| 96 | int vfs_fstat(unsigned int fd, struct kstat *stat) | 106 | int vfs_fstat(unsigned int fd, struct kstat *stat) |
| @@ -151,7 +161,7 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta | |||
| 151 | asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf) | 161 | asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf) |
| 152 | { | 162 | { |
| 153 | struct kstat stat; | 163 | struct kstat stat; |
| 154 | int error = vfs_stat(filename, &stat); | 164 | int error = vfs_stat_fd(AT_FDCWD, filename, &stat); |
| 155 | 165 | ||
| 156 | if (!error) | 166 | if (!error) |
| 157 | error = cp_old_stat(&stat, statbuf); | 167 | error = cp_old_stat(&stat, statbuf); |
| @@ -161,7 +171,7 @@ asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user | |||
| 161 | asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf) | 171 | asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf) |
| 162 | { | 172 | { |
| 163 | struct kstat stat; | 173 | struct kstat stat; |
| 164 | int error = vfs_lstat(filename, &stat); | 174 | int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); |
| 165 | 175 | ||
| 166 | if (!error) | 176 | if (!error) |
| 167 | error = cp_old_stat(&stat, statbuf); | 177 | error = cp_old_stat(&stat, statbuf); |
| @@ -229,27 +239,50 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf) | |||
| 229 | return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; | 239 | return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; |
| 230 | } | 240 | } |
| 231 | 241 | ||
| 232 | asmlinkage long sys_newstat(char __user * filename, struct stat __user * statbuf) | 242 | asmlinkage long sys_newstat(char __user *filename, struct stat __user *statbuf) |
| 233 | { | 243 | { |
| 234 | struct kstat stat; | 244 | struct kstat stat; |
| 235 | int error = vfs_stat(filename, &stat); | 245 | int error = vfs_stat_fd(AT_FDCWD, filename, &stat); |
| 236 | 246 | ||
| 237 | if (!error) | 247 | if (!error) |
| 238 | error = cp_new_stat(&stat, statbuf); | 248 | error = cp_new_stat(&stat, statbuf); |
| 239 | 249 | ||
| 240 | return error; | 250 | return error; |
| 241 | } | 251 | } |
| 242 | asmlinkage long sys_newlstat(char __user * filename, struct stat __user * statbuf) | 252 | |
| 253 | asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf) | ||
| 243 | { | 254 | { |
| 244 | struct kstat stat; | 255 | struct kstat stat; |
| 245 | int error = vfs_lstat(filename, &stat); | 256 | int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); |
| 246 | 257 | ||
| 247 | if (!error) | 258 | if (!error) |
| 248 | error = cp_new_stat(&stat, statbuf); | 259 | error = cp_new_stat(&stat, statbuf); |
| 249 | 260 | ||
| 250 | return error; | 261 | return error; |
| 251 | } | 262 | } |
| 252 | asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf) | 263 | |
| 264 | asmlinkage long sys_newfstatat(int dfd, char __user *filename, | ||
| 265 | struct stat __user *statbuf, int flag) | ||
| 266 | { | ||
| 267 | struct kstat stat; | ||
| 268 | int error = -EINVAL; | ||
| 269 | |||
| 270 | if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) | ||
| 271 | goto out; | ||
| 272 | |||
| 273 | if (flag & AT_SYMLINK_NOFOLLOW) | ||
| 274 | error = vfs_lstat_fd(dfd, filename, &stat); | ||
| 275 | else | ||
| 276 | error = vfs_stat_fd(dfd, filename, &stat); | ||
| 277 | |||
| 278 | if (!error) | ||
| 279 | error = cp_new_stat(&stat, statbuf); | ||
| 280 | |||
| 281 | out: | ||
| 282 | return error; | ||
| 283 | } | ||
| 284 | |||
| 285 | asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf) | ||
| 253 | { | 286 | { |
| 254 | struct kstat stat; | 287 | struct kstat stat; |
| 255 | int error = vfs_fstat(fd, &stat); | 288 | int error = vfs_fstat(fd, &stat); |
| @@ -260,7 +293,8 @@ asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf) | |||
| 260 | return error; | 293 | return error; |
| 261 | } | 294 | } |
| 262 | 295 | ||
| 263 | asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bufsiz) | 296 | asmlinkage long sys_readlinkat(int dfd, const char __user *path, |
| 297 | char __user *buf, int bufsiz) | ||
| 264 | { | 298 | { |
| 265 | struct nameidata nd; | 299 | struct nameidata nd; |
| 266 | int error; | 300 | int error; |
| @@ -268,7 +302,7 @@ asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bu | |||
| 268 | if (bufsiz <= 0) | 302 | if (bufsiz <= 0) |
| 269 | return -EINVAL; | 303 | return -EINVAL; |
| 270 | 304 | ||
| 271 | error = user_path_walk_link(path, &nd); | 305 | error = __user_walk_fd(dfd, path, 0, &nd); |
| 272 | if (!error) { | 306 | if (!error) { |
| 273 | struct inode * inode = nd.dentry->d_inode; | 307 | struct inode * inode = nd.dentry->d_inode; |
| 274 | 308 | ||
| @@ -285,6 +319,12 @@ asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bu | |||
| 285 | return error; | 319 | return error; |
| 286 | } | 320 | } |
| 287 | 321 | ||
| 322 | asmlinkage long sys_readlink(const char __user *path, char __user *buf, | ||
| 323 | int bufsiz) | ||
| 324 | { | ||
| 325 | return sys_readlinkat(AT_FDCWD, path, buf, bufsiz); | ||
| 326 | } | ||
| 327 | |||
| 288 | 328 | ||
| 289 | /* ---------- LFS-64 ----------- */ | 329 | /* ---------- LFS-64 ----------- */ |
| 290 | #ifdef __ARCH_WANT_STAT64 | 330 | #ifdef __ARCH_WANT_STAT64 |
