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

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