You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
3.4 KiB

/*
* linux/fs/file_dev.c
*
* (C) 1991 Linus Torvalds
*/
#include <errno.h>
#include <fcntl.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <sys/types.h>
#include <new.h>
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define PATH_MAX 255
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
{
int left,chars,nr;
struct buffer_head * bh;
if ((left=count)<=0)
return 0;
while (left) {
if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) {
if (!(bh=bread(inode->i_dev,nr)))
break;
} else
bh = NULL;
nr = filp->f_pos % BLOCK_SIZE;
chars = MIN( BLOCK_SIZE-nr , left );
filp->f_pos += chars;
left -= chars;
if (bh) {
char * p = nr + bh->b_data;
while (chars-->0)
put_fs_byte(*(p++),buf++);
brelse(bh);
} else {
while (chars-->0)
put_fs_byte(0,buf++);
}
}
inode->i_atime = CURRENT_TIME;
return (count-left)?(count-left):-ERROR;
}
int file_write(struct m_inode * inode, struct file * filp, char * buf, int count)
{
off_t pos;
int block,c;
struct buffer_head * bh;
char * p;
int i=0;
/*
* ok, append may not work when many processes are writing at the same time
* but so what. That way leads to madness anyway.
*/
if (filp->f_flags & O_APPEND)
pos = inode->i_size;
else
pos = filp->f_pos;
while (i<count) {
if (!(block = create_block(inode,pos/BLOCK_SIZE)))
break;
if (!(bh=bread(inode->i_dev,block)))
break;
c = pos % BLOCK_SIZE;
p = c + bh->b_data;
bh->b_dirt = 1;
c = BLOCK_SIZE-c;
if (c > count-i) c = count-i;
pos += c;
if (pos > inode->i_size) {
inode->i_size = pos;
inode->i_dirt = 1;
}
i += c;
while (c-->0)
*(p++) = get_fs_byte(buf++);
brelse(bh);
}
inode->i_mtime = CURRENT_TIME;
if (!(filp->f_flags & O_APPEND)) {
filp->f_pos = pos;
inode->i_ctime = CURRENT_TIME;
}
return (i?i:-1);
}
int sys_getdents(unsigned int fd, struct linux_dirent *d, unsigned int count)
{
struct linux_dirent tmp;
struct file * file;
struct m_inode * inode;
struct buffer_head * block;
struct dir_entry * ptr;
char * buf;
int bpos;
int dpos;
int ld_size;
int i;
ld_size = sizeof(struct linux_dirent); /* size of linux_dirent */
file = current->filp[fd]; /* opened file */
if (fd >= NR_OPEN)
return -EINVAL;
if (!count)
return -1;
if (!file)
return ENOTDIR;
inode = file->f_inode;
block = bread(inode->i_dev,inode->i_zone[0]);
/* count: size of linux_dirent[], target
* dd_size: size of dir_entry[], block 400?
*/
for (dpos = 0,bpos = 0;bpos<inode->i_size;bpos += sizeof(struct dir_entry)) {
if (dpos >= (count-ld_size))
return 0; /* d full */
ptr = (struct dir_entry *) (bpos + block->b_data);
if (!ptr -> inode)
continue; /* when it 's empty inode, jump it */
tmp.d_ino = ptr -> inode;
for (i = 0; i < 14; i++) tmp.d_name[i] = ptr -> name[i];
tmp.d_reclen = sizeof(tmp);
tmp.d_off = 0;
buf = &tmp;
for (i = 0; i < tmp.d_reclen; i++){
put_fs_byte(*(buf+i),((char*)d)+i+dpos); /* move data from kernel to user */
}
dpos += tmp.d_reclen;
}
return dpos;
}
long sys_mmap(void *start, size_t len, int prot, int flags,
int fd, off_t off)
{
return 0;
}
int sys_munmap(void * start, size_t len)
{
return 0;
}