linux/fs/stat.c
<<
>>
Prefs
   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);
 470