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 not yet used: but we'll probably support reading several entries
  17  * at once in the future. Use count=1 in the library for future expansions.
  18  */
  19 asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  20 {
  21         int error;
  22         struct file * file;
  23         struct inode * inode;
  24 
  25         if (fd >= NR_OPEN || !(file = current->files->fd[fd]) ||
  26             !(inode = file->f_inode))
  27                 return -EBADF;
  28         error = -ENOTDIR;
  29         if (file->f_op && file->f_op->readdir) {
  30                 error = verify_area(VERIFY_WRITE, dirent, sizeof (*dirent));
  31                 if (!error)
  32                         error = file->f_op->readdir(inode,file,dirent,count);
  33         }
  34         return error;
  35 }
  36 
  37 asmlinkage int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39         struct file * file;
  40         int tmp = -1;
  41 
  42         if (fd >= NR_OPEN || !(file=current->files->fd[fd]) || !(file->f_inode))
  43                 return -EBADF;
  44         if (origin > 2)
  45                 return -EINVAL;
  46         if (file->f_op && file->f_op->lseek)
  47                 return file->f_op->lseek(file->f_inode,file,offset,origin);
  48 
  49 /* this is the default handler if no lseek handler is present */
  50         switch (origin) {
  51                 case 0:
  52                         tmp = offset;
  53                         break;
  54                 case 1:
  55                         tmp = file->f_pos + offset;
  56                         break;
  57                 case 2:
  58                         if (!file->f_inode)
  59                                 return -EINVAL;
  60                         tmp = file->f_inode->i_size + offset;
  61                         break;
  62         }
  63         if (tmp < 0)
  64                 return -EINVAL;
  65         file->f_pos = tmp;
  66         file->f_reada = 0;
  67         return file->f_pos;
  68 }
  69 
  70 asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
     /* [previous][next][first][last][top][bottom][index][help] */
  71                           unsigned long offset_low, loff_t * result,
  72                           unsigned int origin)
  73 {
  74         struct file * file;
  75         loff_t tmp = -1;
  76         loff_t offset;
  77         int err;
  78 
  79         if (fd >= NR_OPEN || !(file=current->files->fd[fd]) || !(file->f_inode))
  80                 return -EBADF;
  81         if (origin > 2)
  82                 return -EINVAL;
  83         if ((err = verify_area(VERIFY_WRITE, result, sizeof(loff_t))))
  84                 return err;
  85         offset = (loff_t) (((unsigned long long) offset_high << 32) | offset_low);
  86 /* there is no fs specific llseek handler */
  87         switch (origin) {
  88                 case 0:
  89                         tmp = offset;
  90                         break;
  91                 case 1:
  92                         tmp = file->f_pos + offset;
  93                         break;
  94                 case 2:
  95                         if (!file->f_inode)
  96                                 return -EINVAL;
  97                         tmp = file->f_inode->i_size + offset;
  98                         break;
  99         }
 100         if (tmp < 0)
 101                 return -EINVAL;
 102         file->f_pos = tmp;
 103         file->f_reada = 0;
 104         memcpy_tofs(result, &file->f_pos, sizeof(loff_t));
 105         return 0;
 106 }
 107 
 108 asmlinkage int sys_read(unsigned int fd,char * buf,unsigned int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 109 {
 110         int error;
 111         struct file * file;
 112         struct inode * inode;
 113 
 114         if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
 115                 return -EBADF;
 116         if (!(file->f_mode & 1))
 117                 return -EBADF;
 118         if (!file->f_op || !file->f_op->read)
 119                 return -EINVAL;
 120         if (!count)
 121                 return 0;
 122         error = verify_area(VERIFY_WRITE,buf,count);
 123         if (error)
 124                 return error;
 125         return file->f_op->read(inode,file,buf,count);
 126 }
 127 
 128 asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 129 {
 130         int error;
 131         struct file * file;
 132         struct inode * inode;
 133         int written;
 134         
 135         if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
 136                 return -EBADF;
 137         if (!(file->f_mode & 2))
 138                 return -EBADF;
 139         if (!file->f_op || !file->f_op->write)
 140                 return -EINVAL;
 141         if (!count)
 142                 return 0;
 143         error = verify_area(VERIFY_READ,buf,count);
 144         if (error)
 145                 return error;
 146         written = file->f_op->write(inode,file,buf,count);
 147         /*
 148          * If data has been written to the file, remove the setuid and
 149          * the setgid bits
 150          */
 151         if (written > 0 && !suser() && (inode->i_mode & (S_ISUID | S_ISGID))) {
 152                 inode->i_mode &= ~(S_ISUID | S_ISGID);
 153                 notify_change (NOTIFY_MODE, inode);
 154         }
 155         return written;
 156 }

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