root/fs/read_write.c

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

DEFINITIONS

This source file includes following definitions.
  1. sys_readdir
  2. sys_lseek
  3. sys_llseek
  4. sys_read
  5. sys_write

   1 /*
   2  *  linux/fs/read_write.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #include <linux/types.h>
   8 #include <linux/errno.h>
   9 #include <linux/stat.h>
  10 #include <linux/kernel.h>
  11 #include <linux/sched.h>
  12 
  13 #include <asm/segment.h>
  14 
  15 /*
  16  * Count is now a supported feature, but currently only the ext2fs
  17  * uses it.  A count value of 1 is supported for compatibility with
  18  * earlier libraries, but larger values are supported: count should
  19  * indicate the total buffer space available for filling with dirents.
  20  * The d_off entry in the dirents will then indicate the offset from
  21  * each dirent to the next, and the return value will indicate the
  22  * number of bytes written.  All dirents will be written at
  23  * word-aligned addresses.  [sct Oct 1994]
  24  */
  25 asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 {
  27         int error;
  28         struct file * file;
  29         struct inode * inode;
  30 
  31         if (fd >= NR_OPEN || !(file = current->files->fd[fd]) ||
  32             !(inode = file->f_inode))
  33                 return -EBADF;
  34         error = -ENOTDIR;
  35         if (file->f_op && file->f_op->readdir) {
  36                 int size = count;
  37                 if (count == 1)
  38                         size = sizeof(*dirent);
  39                 error = verify_area(VERIFY_WRITE, dirent, size);
  40                 if (!error)
  41                         error = file->f_op->readdir(inode,file,dirent,count);
  42         }
  43         return error;
  44 }
  45 
  46 asmlinkage int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48         struct file * file;
  49         int tmp = -1;
  50 
  51         if (fd >= NR_OPEN || !(file=current->files->fd[fd]) || !(file->f_inode))
  52                 return -EBADF;
  53         if (origin > 2)
  54                 return -EINVAL;
  55         if (file->f_op && file->f_op->lseek)
  56                 return file->f_op->lseek(file->f_inode,file,offset,origin);
  57 
  58 /* this is the default handler if no lseek handler is present */
  59         switch (origin) {
  60                 case 0:
  61                         tmp = offset;
  62                         break;
  63                 case 1:
  64                         tmp = file->f_pos + offset;
  65                         break;
  66                 case 2:
  67                         if (!file->f_inode)
  68                                 return -EINVAL;
  69                         tmp = file->f_inode->i_size + offset;
  70                         break;
  71         }
  72         if (tmp < 0)
  73                 return -EINVAL;
  74         if (tmp != file->f_pos) {
  75                 file->f_pos = tmp;
  76                 file->f_reada = 0;
  77                 file->f_version = ++event;
  78         }
  79         return file->f_pos;
  80 }
  81 
  82 asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
     /* [previous][next][first][last][top][bottom][index][help] */
  83                           unsigned long offset_low, loff_t * result,
  84                           unsigned int origin)
  85 {
  86         struct file * file;
  87         loff_t tmp = -1;
  88         loff_t offset;
  89         int err;
  90 
  91         if (fd >= NR_OPEN || !(file=current->files->fd[fd]) || !(file->f_inode))
  92                 return -EBADF;
  93         if (origin > 2)
  94                 return -EINVAL;
  95         if ((err = verify_area(VERIFY_WRITE, result, sizeof(loff_t))))
  96                 return err;
  97         offset = (loff_t) (((unsigned long long) offset_high << 32) | offset_low);
  98 /* there is no fs specific llseek handler */
  99         switch (origin) {
 100                 case 0:
 101                         tmp = offset;
 102                         break;
 103                 case 1:
 104                         tmp = file->f_pos + offset;
 105                         break;
 106                 case 2:
 107                         if (!file->f_inode)
 108                                 return -EINVAL;
 109                         tmp = file->f_inode->i_size + offset;
 110                         break;
 111         }
 112         if (tmp < 0)
 113                 return -EINVAL;
 114         file->f_pos = tmp;
 115         file->f_reada = 0;
 116         file->f_version = ++event;
 117         memcpy_tofs(result, &file->f_pos, sizeof(loff_t));
 118         return 0;
 119 }
 120 
 121 asmlinkage int sys_read(unsigned int fd,char * buf,unsigned int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123         int error;
 124         struct file * file;
 125         struct inode * inode;
 126 
 127         if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
 128                 return -EBADF;
 129         if (!(file->f_mode & 1))
 130                 return -EBADF;
 131         if (!file->f_op || !file->f_op->read)
 132                 return -EINVAL;
 133         if (!count)
 134                 return 0;
 135         error = verify_area(VERIFY_WRITE,buf,count);
 136         if (error)
 137                 return error;
 138         return file->f_op->read(inode,file,buf,count);
 139 }
 140 
 141 asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 142 {
 143         int error;
 144         struct file * file;
 145         struct inode * inode;
 146         int written;
 147         
 148         if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
 149                 return -EBADF;
 150         if (!(file->f_mode & 2))
 151                 return -EBADF;
 152         if (!file->f_op || !file->f_op->write)
 153                 return -EINVAL;
 154         if (!count)
 155                 return 0;
 156         error = verify_area(VERIFY_READ,buf,count);
 157         if (error)
 158                 return error;
 159         written = file->f_op->write(inode,file,buf,count);
 160         /*
 161          * If data has been written to the file, remove the setuid and
 162          * the setgid bits
 163          */
 164         if (written > 0 && !suser() && (inode->i_mode & (S_ISUID | S_ISGID))) {
 165                 struct iattr newattrs;
 166                 newattrs.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
 167                 newattrs.ia_valid = ATTR_MODE;
 168                 notify_change(inode, &newattrs);
 169         }
 170         return written;
 171 }

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