linux-old/fs/stat.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/stat.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 */
   6
   7#include <linux/mm.h>
   8#include <linux/errno.h>
   9#include <linux/file.h>
  10#include <linux/smp_lock.h>
  11
  12#include <asm/uaccess.h>
  13
  14/*
  15 * Revalidate the inode. This is required for proper NFS attribute caching.
  16 */
  17static __inline__ int
  18do_revalidate(struct dentry *dentry)
  19{
  20        struct inode * inode = dentry->d_inode;
  21        if (inode->i_op && inode->i_op->revalidate)
  22                return inode->i_op->revalidate(dentry);
  23        return 0;
  24}
  25
  26
  27#if !defined(__alpha__) && !defined(__sparc__)
  28
  29/*
  30 * For backward compatibility?  Maybe this should be moved
  31 * into arch/i386 instead?
  32 */
  33static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
  34{
  35        static int warncount = 5;
  36        struct __old_kernel_stat tmp;
  37
  38        if (warncount) {
  39                warncount--;
  40                printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
  41                        current->comm);
  42        }
  43
  44        tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  45        tmp.st_ino = inode->i_ino;
  46        tmp.st_mode = inode->i_mode;
  47        tmp.st_nlink = inode->i_nlink;
  48        tmp.st_uid = inode->i_uid;
  49        tmp.st_gid = inode->i_gid;
  50        tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  51        tmp.st_size = inode->i_size;
  52        tmp.st_atime = inode->i_atime;
  53        tmp.st_mtime = inode->i_mtime;
  54        tmp.st_ctime = inode->i_ctime;
  55        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
  56}
  57
  58#endif
  59
  60static int cp_new_stat(struct inode * inode, struct stat * statbuf)
  61{
  62        struct stat tmp;
  63        unsigned int blocks, indirect;
  64
  65        memset(&tmp, 0, sizeof(tmp));
  66        tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  67        tmp.st_ino = inode->i_ino;
  68        tmp.st_mode = inode->i_mode;
  69        tmp.st_nlink = inode->i_nlink;
  70        tmp.st_uid = inode->i_uid;
  71        tmp.st_gid = inode->i_gid;
  72        tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  73        tmp.st_size = inode->i_size;
  74        tmp.st_atime = inode->i_atime;
  75        tmp.st_mtime = inode->i_mtime;
  76        tmp.st_ctime = inode->i_ctime;
  77/*
  78 * st_blocks and st_blksize are approximated with a simple algorithm if
  79 * they aren't supported directly by the filesystem. The minix and msdos
  80 * filesystems don't keep track of blocks, so they would either have to
  81 * be counted explicitly (by delving into the file itself), or by using
  82 * this simple algorithm to get a reasonable (although not 100% accurate)
  83 * value.
  84 */
  85
  86/*
  87 * Use minix fs values for the number of direct and indirect blocks.  The
  88 * count is now exact for the minix fs except that it counts zero blocks.
  89 * Everything is in units of BLOCK_SIZE until the assignment to
  90 * tmp.st_blksize.
  91 */
  92#define D_B   7
  93#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
  94
  95        if (!inode->i_blksize) {
  96                blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
  97                if (blocks > D_B) {
  98                        indirect = (blocks - D_B + I_B - 1) / I_B;
  99                        blocks += indirect;
 100                        if (indirect > 1) {
 101                                indirect = (indirect - 1 + I_B - 1) / I_B;
 102                                blocks += indirect;
 103                                if (indirect > 1)
 104                                        blocks++;
 105                        }
 106                }
 107                tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
 108                tmp.st_blksize = BLOCK_SIZE;
 109        } else {
 110                tmp.st_blocks = inode->i_blocks;
 111                tmp.st_blksize = inode->i_blksize;
 112        }
 113        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 114}
 115
 116
 117#if !defined(__alpha__) && !defined(__sparc__)
 118/*
 119 * For backward compatibility?  Maybe this should be moved
 120 * into arch/i386 instead?
 121 */
 122asmlinkage int sys_stat(char * filename, struct __old_kernel_stat * statbuf)
 123{
 124        struct dentry * dentry;
 125        int error;
 126
 127        lock_kernel();
 128        dentry = namei(filename);
 129
 130        error = PTR_ERR(dentry);
 131        if (!IS_ERR(dentry)) {
 132                error = do_revalidate(dentry);
 133                if (!error)
 134                        error = cp_old_stat(dentry->d_inode, statbuf);
 135
 136                dput(dentry);
 137        }
 138        unlock_kernel();
 139        return error;
 140}
 141#endif
 142
 143asmlinkage int sys_newstat(char * filename, struct stat * statbuf)
 144{
 145        struct dentry * dentry;
 146        int error;
 147
 148        lock_kernel();
 149        dentry = namei(filename);
 150
 151        error = PTR_ERR(dentry);
 152        if (!IS_ERR(dentry)) {
 153                error = do_revalidate(dentry);
 154                if (!error)
 155                        error = cp_new_stat(dentry->d_inode, statbuf);
 156
 157                dput(dentry);
 158        }
 159        unlock_kernel();
 160        return error;
 161}
 162
 163#if !defined(__alpha__) && !defined(__sparc__)
 164
 165/*
 166 * For backward compatibility?  Maybe this should be moved
 167 * into arch/i386 instead?
 168 */
 169asmlinkage int sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
 170{
 171        struct dentry * dentry;
 172        int error;
 173
 174        lock_kernel();
 175        dentry = lnamei(filename);
 176
 177        error = PTR_ERR(dentry);
 178        if (!IS_ERR(dentry)) {
 179                error = do_revalidate(dentry);
 180                if (!error)
 181                        error = cp_old_stat(dentry->d_inode, statbuf);
 182
 183                dput(dentry);
 184        }
 185        unlock_kernel();
 186        return error;
 187}
 188
 189#endif
 190
 191asmlinkage int sys_newlstat(char * filename, struct stat * statbuf)
 192{
 193        struct dentry * dentry;
 194        int error;
 195
 196        lock_kernel();
 197        dentry = lnamei(filename);
 198
 199        error = PTR_ERR(dentry);
 200        if (!IS_ERR(dentry)) {
 201                error = do_revalidate(dentry);
 202                if (!error)
 203                        error = cp_new_stat(dentry->d_inode, statbuf);
 204
 205                dput(dentry);
 206        }
 207        unlock_kernel();
 208        return error;
 209}
 210
 211#if !defined(__alpha__) && !defined(__sparc__)
 212
 213/*
 214 * For backward compatibility?  Maybe this should be moved
 215 * into arch/i386 instead?
 216 */
 217asmlinkage int sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf)
 218{
 219        struct file * f;
 220        int err = -EBADF;
 221
 222        lock_kernel();
 223        f = fget(fd);
 224        if (f) {
 225                struct dentry * dentry = f->f_dentry;
 226
 227                err = do_revalidate(dentry);
 228                if (!err)
 229                        err = cp_old_stat(dentry->d_inode, statbuf);
 230                fput(f);
 231        }
 232        unlock_kernel();
 233        return err;
 234}
 235
 236#endif
 237
 238asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf)
 239{
 240        struct file * f;
 241        int err = -EBADF;
 242
 243        lock_kernel();
 244        f = fget(fd);
 245        if (f) {
 246                struct dentry * dentry = f->f_dentry;
 247
 248                err = do_revalidate(dentry);
 249                if (!err)
 250                        err = cp_new_stat(dentry->d_inode, statbuf);
 251                fput(f);
 252        }
 253        unlock_kernel();
 254        return err;
 255}
 256
 257asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz)
 258{
 259        struct dentry * dentry;
 260        int error;
 261
 262        if (bufsiz <= 0)
 263                return -EINVAL;
 264
 265        lock_kernel();
 266        dentry = lnamei(path);
 267
 268        error = PTR_ERR(dentry);
 269        if (!IS_ERR(dentry)) {
 270                struct inode * inode = dentry->d_inode;
 271
 272                error = -EINVAL;
 273                if (inode->i_op && inode->i_op->readlink &&
 274                    !(error = do_revalidate(dentry))) {
 275                        UPDATE_ATIME(inode);
 276                        error = inode->i_op->readlink(dentry, buf, bufsiz);
 277                }
 278                dput(dentry);
 279        }
 280        unlock_kernel();
 281        return error;
 282}
 283
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.