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