LTP GCOV extension - code coverage report
Current view: directory - fs - stat.c
Test: 2.6.14_rebootonly_gcov.info
Date: 2006-05-22 Instrumented lines: 222
Code covered: 54.5 % Executed lines: 121

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

Generated by: LTP GCOV extension version 1.4