root/fs/read_write.c

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

DEFINITIONS

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

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