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