root/fs/stat.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cp_old_stat
  2. cp_new_stat
  3. sys_stat
  4. sys_newstat
  5. sys_lstat
  6. sys_newlstat
  7. sys_fstat
  8. sys_newfstat
  9. sys_readlink

   1 /*
   2  *  linux/fs/stat.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #include <linux/errno.h>
   8 #include <linux/string.h>
   9 #include <linux/stat.h>
  10 #include <linux/fs.h>
  11 #include <linux/sched.h>
  12 #include <linux/kernel.h>
  13 #include <linux/mm.h>
  14 
  15 #include <asm/segment.h>
  16 
  17 #ifndef __alpha__
  18 
  19 /*
  20  * For backward compatibility?  Maybe this should be moved
  21  * into arch/i386 instead?
  22  */
  23 static void cp_old_stat(struct inode * inode, struct old_stat * statbuf)
     /* [previous][next][first][last][top][bottom][index][help] */
  24 {
  25         struct old_stat tmp;
  26 
  27         printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
  28                 current->comm);
  29         tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  30         tmp.st_ino = inode->i_ino;
  31         tmp.st_mode = inode->i_mode;
  32         tmp.st_nlink = inode->i_nlink;
  33         tmp.st_uid = inode->i_uid;
  34         tmp.st_gid = inode->i_gid;
  35         tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  36         tmp.st_size = inode->i_size;
  37         if (inode->i_pipe)
  38                 tmp.st_size = PIPE_SIZE(*inode);
  39         tmp.st_atime = inode->i_atime;
  40         tmp.st_mtime = inode->i_mtime;
  41         tmp.st_ctime = inode->i_ctime;
  42         memcpy_tofs(statbuf,&tmp,sizeof(tmp));
  43 }
  44 
  45 #endif
  46 
  47 static void cp_new_stat(struct inode * inode, struct new_stat * statbuf)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49         struct new_stat tmp;
  50         unsigned int blocks, indirect;
  51 
  52         memset(&tmp, 0, sizeof(tmp));
  53         tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  54         tmp.st_ino = inode->i_ino;
  55         tmp.st_mode = inode->i_mode;
  56         tmp.st_nlink = inode->i_nlink;
  57         tmp.st_uid = inode->i_uid;
  58         tmp.st_gid = inode->i_gid;
  59         tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  60         tmp.st_size = inode->i_size;
  61         if (inode->i_pipe)
  62                 tmp.st_size = PIPE_SIZE(*inode);
  63         tmp.st_atime = inode->i_atime;
  64         tmp.st_mtime = inode->i_mtime;
  65         tmp.st_ctime = inode->i_ctime;
  66 /*
  67  * st_blocks and st_blksize are approximated with a simple algorithm if
  68  * they aren't supported directly by the filesystem. The minix and msdos
  69  * filesystems don't keep track of blocks, so they would either have to
  70  * be counted explicitly (by delving into the file itself), or by using
  71  * this simple algorithm to get a reasonable (although not 100% accurate)
  72  * value.
  73  */
  74 
  75 /*
  76  * Use minix fs values for the number of direct and indirect blocks.  The
  77  * count is now exact for the minix fs except that it counts zero blocks.
  78  * Everything is in BLOCK_SIZE'd units until the assignment to
  79  * tmp.st_blksize.
  80  */
  81 #define D_B   7
  82 #define I_B   (BLOCK_SIZE / sizeof(unsigned short))
  83 
  84         if (!inode->i_blksize) {
  85                 blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
  86                 if (blocks > D_B) {
  87                         indirect = (blocks - D_B + I_B - 1) / I_B;
  88                         blocks += indirect;
  89                         if (indirect > 1) {
  90                                 indirect = (indirect - 1 + I_B - 1) / I_B;
  91                                 blocks += indirect;
  92                                 if (indirect > 1)
  93                                         blocks++;
  94                         }
  95                 }
  96                 tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
  97                 tmp.st_blksize = BLOCK_SIZE;
  98         } else {
  99                 tmp.st_blocks = inode->i_blocks;
 100                 tmp.st_blksize = inode->i_blksize;
 101         }
 102         memcpy_tofs(statbuf,&tmp,sizeof(tmp));
 103 }
 104 
 105 #ifndef __alpha__
 106 /*
 107  * For backward compatibility?  Maybe this should be moved
 108  * into arch/i386 instead?
 109  */
 110 asmlinkage int sys_stat(char * filename, struct old_stat * statbuf)
     /* [previous][next][first][last][top][bottom][index][help] */
 111 {
 112         struct inode * inode;
 113         int error;
 114 
 115         error = verify_area(VERIFY_WRITE,statbuf,sizeof (*statbuf));
 116         if (error)
 117                 return error;
 118         error = namei(filename,&inode);
 119         if (error)
 120                 return error;
 121         cp_old_stat(inode,statbuf);
 122         iput(inode);
 123         return 0;
 124 }
 125 #endif
 126 
 127 asmlinkage int sys_newstat(char * filename, struct new_stat * statbuf)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129         struct inode * inode;
 130         int error;
 131 
 132         error = verify_area(VERIFY_WRITE,statbuf,sizeof (*statbuf));
 133         if (error)
 134                 return error;
 135         error = namei(filename,&inode);
 136         if (error)
 137                 return error;
 138         cp_new_stat(inode,statbuf);
 139         iput(inode);
 140         return 0;
 141 }
 142 
 143 #ifndef __alpha__
 144 
 145 /*
 146  * For backward compatibility?  Maybe this should be moved
 147  * into arch/i386 instead?
 148  */
 149 asmlinkage int sys_lstat(char * filename, struct old_stat * statbuf)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151         struct inode * inode;
 152         int error;
 153 
 154         error = verify_area(VERIFY_WRITE,statbuf,sizeof (*statbuf));
 155         if (error)
 156                 return error;
 157         error = lnamei(filename,&inode);
 158         if (error)
 159                 return error;
 160         cp_old_stat(inode,statbuf);
 161         iput(inode);
 162         return 0;
 163 }
 164 
 165 #endif
 166 
 167 asmlinkage int sys_newlstat(char * filename, struct new_stat * statbuf)
     /* [previous][next][first][last][top][bottom][index][help] */
 168 {
 169         struct inode * inode;
 170         int error;
 171 
 172         error = verify_area(VERIFY_WRITE,statbuf,sizeof (*statbuf));
 173         if (error)
 174                 return error;
 175         error = lnamei(filename,&inode);
 176         if (error)
 177                 return error;
 178         cp_new_stat(inode,statbuf);
 179         iput(inode);
 180         return 0;
 181 }
 182 
 183 #ifndef __alpha__
 184 
 185 /*
 186  * For backward compatibility?  Maybe this should be moved
 187  * into arch/i386 instead?
 188  */
 189 asmlinkage int sys_fstat(unsigned int fd, struct old_stat * statbuf)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191         struct file * f;
 192         struct inode * inode;
 193         int error;
 194 
 195         error = verify_area(VERIFY_WRITE,statbuf,sizeof (*statbuf));
 196         if (error)
 197                 return error;
 198         if (fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
 199                 return -EBADF;
 200         cp_old_stat(inode,statbuf);
 201         return 0;
 202 }
 203 
 204 #endif
 205 
 206 asmlinkage int sys_newfstat(unsigned int fd, struct new_stat * statbuf)
     /* [previous][next][first][last][top][bottom][index][help] */
 207 {
 208         struct file * f;
 209         struct inode * inode;
 210         int error;
 211 
 212         error = verify_area(VERIFY_WRITE,statbuf,sizeof (*statbuf));
 213         if (error)
 214                 return error;
 215         if (fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
 216                 return -EBADF;
 217         cp_new_stat(inode,statbuf);
 218         return 0;
 219 }
 220 
 221 asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 222 {
 223         struct inode * inode;
 224         int error;
 225 
 226         if (bufsiz <= 0)
 227                 return -EINVAL;
 228         error = verify_area(VERIFY_WRITE,buf,bufsiz);
 229         if (error)
 230                 return error;
 231         error = lnamei(path,&inode);
 232         if (error)
 233                 return error;
 234         if (!inode->i_op || !inode->i_op->readlink) {
 235                 iput(inode);
 236                 return -EINVAL;
 237         }
 238         return inode->i_op->readlink(inode,buf,bufsiz);
 239 }

/* [previous][next][first][last][top][bottom][index][help] */