home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / read_write.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  4.2 KB  |  173 lines

  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)
  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)
  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,
  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)
  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)
  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. }
  173.