at v2.6.38-rc2 469 lines 11 kB view raw
1/* 2 * linux/fs/stat.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 7#include <linux/module.h> 8#include <linux/mm.h> 9#include <linux/errno.h> 10#include <linux/file.h> 11#include <linux/highuid.h> 12#include <linux/fs.h> 13#include <linux/namei.h> 14#include <linux/security.h> 15#include <linux/syscalls.h> 16#include <linux/pagemap.h> 17 18#include <asm/uaccess.h> 19#include <asm/unistd.h> 20 21void generic_fillattr(struct inode *inode, struct kstat *stat) 22{ 23 stat->dev = inode->i_sb->s_dev; 24 stat->ino = inode->i_ino; 25 stat->mode = inode->i_mode; 26 stat->nlink = inode->i_nlink; 27 stat->uid = inode->i_uid; 28 stat->gid = inode->i_gid; 29 stat->rdev = inode->i_rdev; 30 stat->atime = inode->i_atime; 31 stat->mtime = inode->i_mtime; 32 stat->ctime = inode->i_ctime; 33 stat->size = i_size_read(inode); 34 stat->blocks = inode->i_blocks; 35 stat->blksize = (1 << inode->i_blkbits); 36} 37 38EXPORT_SYMBOL(generic_fillattr); 39 40int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) 41{ 42 struct inode *inode = dentry->d_inode; 43 int retval; 44 45 retval = security_inode_getattr(mnt, dentry); 46 if (retval) 47 return retval; 48 49 if (inode->i_op->getattr) 50 return inode->i_op->getattr(mnt, dentry, stat); 51 52 generic_fillattr(inode, stat); 53 return 0; 54} 55 56EXPORT_SYMBOL(vfs_getattr); 57 58int vfs_fstat(unsigned int fd, struct kstat *stat) 59{ 60 struct file *f = fget(fd); 61 int error = -EBADF; 62 63 if (f) { 64 error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat); 65 fput(f); 66 } 67 return error; 68} 69EXPORT_SYMBOL(vfs_fstat); 70 71int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, 72 int flag) 73{ 74 struct path path; 75 int error = -EINVAL; 76 int lookup_flags = 0; 77 78 if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0) 79 goto out; 80 81 if (!(flag & AT_SYMLINK_NOFOLLOW)) 82 lookup_flags |= LOOKUP_FOLLOW; 83 if (flag & AT_NO_AUTOMOUNT) 84 lookup_flags |= LOOKUP_NO_AUTOMOUNT; 85 86 error = user_path_at(dfd, filename, lookup_flags, &path); 87 if (error) 88 goto out; 89 90 error = vfs_getattr(path.mnt, path.dentry, stat); 91 path_put(&path); 92out: 93 return error; 94} 95EXPORT_SYMBOL(vfs_fstatat); 96 97int vfs_stat(const char __user *name, struct kstat *stat) 98{ 99 return vfs_fstatat(AT_FDCWD, name, stat, 0); 100} 101EXPORT_SYMBOL(vfs_stat); 102 103int vfs_lstat(const char __user *name, struct kstat *stat) 104{ 105 return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW); 106} 107EXPORT_SYMBOL(vfs_lstat); 108 109 110#ifdef __ARCH_WANT_OLD_STAT 111 112/* 113 * For backward compatibility? Maybe this should be moved 114 * into arch/i386 instead? 115 */ 116static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf) 117{ 118 static int warncount = 5; 119 struct __old_kernel_stat tmp; 120 121 if (warncount > 0) { 122 warncount--; 123 printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n", 124 current->comm); 125 } else if (warncount < 0) { 126 /* it's laughable, but... */ 127 warncount = 0; 128 } 129 130 memset(&tmp, 0, sizeof(struct __old_kernel_stat)); 131 tmp.st_dev = old_encode_dev(stat->dev); 132 tmp.st_ino = stat->ino; 133 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) 134 return -EOVERFLOW; 135 tmp.st_mode = stat->mode; 136 tmp.st_nlink = stat->nlink; 137 if (tmp.st_nlink != stat->nlink) 138 return -EOVERFLOW; 139 SET_UID(tmp.st_uid, stat->uid); 140 SET_GID(tmp.st_gid, stat->gid); 141 tmp.st_rdev = old_encode_dev(stat->rdev); 142#if BITS_PER_LONG == 32 143 if (stat->size > MAX_NON_LFS) 144 return -EOVERFLOW; 145#endif 146 tmp.st_size = stat->size; 147 tmp.st_atime = stat->atime.tv_sec; 148 tmp.st_mtime = stat->mtime.tv_sec; 149 tmp.st_ctime = stat->ctime.tv_sec; 150 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 151} 152 153SYSCALL_DEFINE2(stat, const char __user *, filename, 154 struct __old_kernel_stat __user *, statbuf) 155{ 156 struct kstat stat; 157 int error; 158 159 error = vfs_stat(filename, &stat); 160 if (error) 161 return error; 162 163 return cp_old_stat(&stat, statbuf); 164} 165 166SYSCALL_DEFINE2(lstat, const char __user *, filename, 167 struct __old_kernel_stat __user *, statbuf) 168{ 169 struct kstat stat; 170 int error; 171 172 error = vfs_lstat(filename, &stat); 173 if (error) 174 return error; 175 176 return cp_old_stat(&stat, statbuf); 177} 178 179SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf) 180{ 181 struct kstat stat; 182 int error = vfs_fstat(fd, &stat); 183 184 if (!error) 185 error = cp_old_stat(&stat, statbuf); 186 187 return error; 188} 189 190#endif /* __ARCH_WANT_OLD_STAT */ 191 192static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf) 193{ 194 struct stat tmp; 195 196#if BITS_PER_LONG == 32 197 if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev)) 198 return -EOVERFLOW; 199#else 200 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) 201 return -EOVERFLOW; 202#endif 203 204 memset(&tmp, 0, sizeof(tmp)); 205#if BITS_PER_LONG == 32 206 tmp.st_dev = old_encode_dev(stat->dev); 207#else 208 tmp.st_dev = new_encode_dev(stat->dev); 209#endif 210 tmp.st_ino = stat->ino; 211 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) 212 return -EOVERFLOW; 213 tmp.st_mode = stat->mode; 214 tmp.st_nlink = stat->nlink; 215 if (tmp.st_nlink != stat->nlink) 216 return -EOVERFLOW; 217 SET_UID(tmp.st_uid, stat->uid); 218 SET_GID(tmp.st_gid, stat->gid); 219#if BITS_PER_LONG == 32 220 tmp.st_rdev = old_encode_dev(stat->rdev); 221#else 222 tmp.st_rdev = new_encode_dev(stat->rdev); 223#endif 224#if BITS_PER_LONG == 32 225 if (stat->size > MAX_NON_LFS) 226 return -EOVERFLOW; 227#endif 228 tmp.st_size = stat->size; 229 tmp.st_atime = stat->atime.tv_sec; 230 tmp.st_mtime = stat->mtime.tv_sec; 231 tmp.st_ctime = stat->ctime.tv_sec; 232#ifdef STAT_HAVE_NSEC 233 tmp.st_atime_nsec = stat->atime.tv_nsec; 234 tmp.st_mtime_nsec = stat->mtime.tv_nsec; 235 tmp.st_ctime_nsec = stat->ctime.tv_nsec; 236#endif 237 tmp.st_blocks = stat->blocks; 238 tmp.st_blksize = stat->blksize; 239 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 240} 241 242SYSCALL_DEFINE2(newstat, const char __user *, filename, 243 struct stat __user *, statbuf) 244{ 245 struct kstat stat; 246 int error = vfs_stat(filename, &stat); 247 248 if (error) 249 return error; 250 return cp_new_stat(&stat, statbuf); 251} 252 253SYSCALL_DEFINE2(newlstat, const char __user *, filename, 254 struct stat __user *, statbuf) 255{ 256 struct kstat stat; 257 int error; 258 259 error = vfs_lstat(filename, &stat); 260 if (error) 261 return error; 262 263 return cp_new_stat(&stat, statbuf); 264} 265 266#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT) 267SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename, 268 struct stat __user *, statbuf, int, flag) 269{ 270 struct kstat stat; 271 int error; 272 273 error = vfs_fstatat(dfd, filename, &stat, flag); 274 if (error) 275 return error; 276 return cp_new_stat(&stat, statbuf); 277} 278#endif 279 280SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf) 281{ 282 struct kstat stat; 283 int error = vfs_fstat(fd, &stat); 284 285 if (!error) 286 error = cp_new_stat(&stat, statbuf); 287 288 return error; 289} 290 291SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname, 292 char __user *, buf, int, bufsiz) 293{ 294 struct path path; 295 int error; 296 297 if (bufsiz <= 0) 298 return -EINVAL; 299 300 error = user_path_at(dfd, pathname, 0, &path); 301 if (!error) { 302 struct inode *inode = path.dentry->d_inode; 303 304 error = -EINVAL; 305 if (inode->i_op->readlink) { 306 error = security_inode_readlink(path.dentry); 307 if (!error) { 308 touch_atime(path.mnt, path.dentry); 309 error = inode->i_op->readlink(path.dentry, 310 buf, bufsiz); 311 } 312 } 313 path_put(&path); 314 } 315 return error; 316} 317 318SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf, 319 int, bufsiz) 320{ 321 return sys_readlinkat(AT_FDCWD, path, buf, bufsiz); 322} 323 324 325/* ---------- LFS-64 ----------- */ 326#ifdef __ARCH_WANT_STAT64 327 328static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf) 329{ 330 struct stat64 tmp; 331 332 memset(&tmp, 0, sizeof(struct stat64)); 333#ifdef CONFIG_MIPS 334 /* mips has weird padding, so we don't get 64 bits there */ 335 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) 336 return -EOVERFLOW; 337 tmp.st_dev = new_encode_dev(stat->dev); 338 tmp.st_rdev = new_encode_dev(stat->rdev); 339#else 340 tmp.st_dev = huge_encode_dev(stat->dev); 341 tmp.st_rdev = huge_encode_dev(stat->rdev); 342#endif 343 tmp.st_ino = stat->ino; 344 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino) 345 return -EOVERFLOW; 346#ifdef STAT64_HAS_BROKEN_ST_INO 347 tmp.__st_ino = stat->ino; 348#endif 349 tmp.st_mode = stat->mode; 350 tmp.st_nlink = stat->nlink; 351 tmp.st_uid = stat->uid; 352 tmp.st_gid = stat->gid; 353 tmp.st_atime = stat->atime.tv_sec; 354 tmp.st_atime_nsec = stat->atime.tv_nsec; 355 tmp.st_mtime = stat->mtime.tv_sec; 356 tmp.st_mtime_nsec = stat->mtime.tv_nsec; 357 tmp.st_ctime = stat->ctime.tv_sec; 358 tmp.st_ctime_nsec = stat->ctime.tv_nsec; 359 tmp.st_size = stat->size; 360 tmp.st_blocks = stat->blocks; 361 tmp.st_blksize = stat->blksize; 362 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 363} 364 365SYSCALL_DEFINE2(stat64, const char __user *, filename, 366 struct stat64 __user *, statbuf) 367{ 368 struct kstat stat; 369 int error = vfs_stat(filename, &stat); 370 371 if (!error) 372 error = cp_new_stat64(&stat, statbuf); 373 374 return error; 375} 376 377SYSCALL_DEFINE2(lstat64, const char __user *, filename, 378 struct stat64 __user *, statbuf) 379{ 380 struct kstat stat; 381 int error = vfs_lstat(filename, &stat); 382 383 if (!error) 384 error = cp_new_stat64(&stat, statbuf); 385 386 return error; 387} 388 389SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf) 390{ 391 struct kstat stat; 392 int error = vfs_fstat(fd, &stat); 393 394 if (!error) 395 error = cp_new_stat64(&stat, statbuf); 396 397 return error; 398} 399 400SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename, 401 struct stat64 __user *, statbuf, int, flag) 402{ 403 struct kstat stat; 404 int error; 405 406 error = vfs_fstatat(dfd, filename, &stat, flag); 407 if (error) 408 return error; 409 return cp_new_stat64(&stat, statbuf); 410} 411#endif /* __ARCH_WANT_STAT64 */ 412 413/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */ 414void __inode_add_bytes(struct inode *inode, loff_t bytes) 415{ 416 inode->i_blocks += bytes >> 9; 417 bytes &= 511; 418 inode->i_bytes += bytes; 419 if (inode->i_bytes >= 512) { 420 inode->i_blocks++; 421 inode->i_bytes -= 512; 422 } 423} 424 425void inode_add_bytes(struct inode *inode, loff_t bytes) 426{ 427 spin_lock(&inode->i_lock); 428 __inode_add_bytes(inode, bytes); 429 spin_unlock(&inode->i_lock); 430} 431 432EXPORT_SYMBOL(inode_add_bytes); 433 434void inode_sub_bytes(struct inode *inode, loff_t bytes) 435{ 436 spin_lock(&inode->i_lock); 437 inode->i_blocks -= bytes >> 9; 438 bytes &= 511; 439 if (inode->i_bytes < bytes) { 440 inode->i_blocks--; 441 inode->i_bytes += 512; 442 } 443 inode->i_bytes -= bytes; 444 spin_unlock(&inode->i_lock); 445} 446 447EXPORT_SYMBOL(inode_sub_bytes); 448 449loff_t inode_get_bytes(struct inode *inode) 450{ 451 loff_t ret; 452 453 spin_lock(&inode->i_lock); 454 ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes; 455 spin_unlock(&inode->i_lock); 456 return ret; 457} 458 459EXPORT_SYMBOL(inode_get_bytes); 460 461void inode_set_bytes(struct inode *inode, loff_t bytes) 462{ 463 /* Caller is here responsible for sufficient locking 464 * (ie. inode->i_lock) */ 465 inode->i_blocks = bytes >> 9; 466 inode->i_bytes = bytes & 511; 467} 468 469EXPORT_SYMBOL(inode_set_bytes);