108 lines
2.5 KiB
C
108 lines
2.5 KiB
C
/*
|
|
* linux/fs/read_write.c
|
|
*
|
|
* Copyright (C) 1991, 1992 Linus Torvalds
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/stat.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/sched.h>
|
|
|
|
#include <asm/segment.h>
|
|
|
|
/*
|
|
* Count is not yet used: but we'll probably support reading several entries
|
|
* at once in the future. Use count=1 in the library for future expansions.
|
|
*/
|
|
asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count)
|
|
{
|
|
int error;
|
|
struct file * file;
|
|
struct inode * inode;
|
|
|
|
if (fd >= NR_OPEN || !(file = current->filp[fd]) ||
|
|
!(inode = file->f_inode))
|
|
return -EBADF;
|
|
error = -ENOTDIR;
|
|
if (file->f_op && file->f_op->readdir) {
|
|
error = verify_area(VERIFY_WRITE, dirent, sizeof (*dirent));
|
|
if (!error)
|
|
error = file->f_op->readdir(inode,file,dirent,count);
|
|
}
|
|
return error;
|
|
}
|
|
|
|
asmlinkage int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
|
|
{
|
|
struct file * file;
|
|
int tmp = -1;
|
|
|
|
if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode))
|
|
return -EBADF;
|
|
if (origin > 2)
|
|
return -EINVAL;
|
|
if (file->f_op && file->f_op->lseek)
|
|
return file->f_op->lseek(file->f_inode,file,offset,origin);
|
|
|
|
/* this is the default handler if no lseek handler is present */
|
|
switch (origin) {
|
|
case 0:
|
|
tmp = offset;
|
|
break;
|
|
case 1:
|
|
tmp = file->f_pos + offset;
|
|
break;
|
|
case 2:
|
|
if (!file->f_inode)
|
|
return -EINVAL;
|
|
tmp = file->f_inode->i_size + offset;
|
|
break;
|
|
}
|
|
if (tmp < 0)
|
|
return -EINVAL;
|
|
file->f_pos = tmp;
|
|
file->f_reada = 0;
|
|
return file->f_pos;
|
|
}
|
|
|
|
asmlinkage int sys_read(unsigned int fd,char * buf,unsigned int count)
|
|
{
|
|
int error;
|
|
struct file * file;
|
|
struct inode * inode;
|
|
|
|
if (fd>=NR_OPEN || !(file=current->filp[fd]) || !(inode=file->f_inode))
|
|
return -EBADF;
|
|
if (!(file->f_mode & 1))
|
|
return -EBADF;
|
|
if (!file->f_op || !file->f_op->read)
|
|
return -EINVAL;
|
|
if (!count)
|
|
return 0;
|
|
error = verify_area(VERIFY_WRITE,buf,count);
|
|
if (error)
|
|
return error;
|
|
return file->f_op->read(inode,file,buf,count);
|
|
}
|
|
|
|
asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count)
|
|
{
|
|
int error;
|
|
struct file * file;
|
|
struct inode * inode;
|
|
|
|
if (fd>=NR_OPEN || !(file=current->filp[fd]) || !(inode=file->f_inode))
|
|
return -EBADF;
|
|
if (!(file->f_mode & 2))
|
|
return -EBADF;
|
|
if (!file->f_op || !file->f_op->write)
|
|
return -EINVAL;
|
|
if (!count)
|
|
return 0;
|
|
error = verify_area(VERIFY_READ,buf,count);
|
|
if (error)
|
|
return error;
|
|
return file->f_op->write(inode,file,buf,count);
|
|
}
|