diff --git a/fs/Makefile b/fs/Makefile index 86ea0fd7b8c97aa91d49d5eb59342ff559e7a8aa..28fa41a280392fe8f7d8a1935566792208291843 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -4,7 +4,7 @@ CCFLAG := -I../include -nostdinc -ffreestanding -Wall -fomit-frame-pointer -fno- LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 INCDIR := ../include OBJS := read_write.o buffer.o super.o open.o file_table.o inode.o namei.o fcntl.o char_dev.o \ - bitmap.o truncate.o exec.o ioctl.o stat.o file_dev.o + bitmap.o truncate.o exec.o ioctl.o stat.o file_dev.o pipe.o fs.o : $(OBJS) $(LD) -m elf_i386 -r -o $@ $^ @@ -54,6 +54,9 @@ stat.o : stat.c file_dev.o : file_dev.c $(GCC) $(CCFLAG) -o $@ $< +pipe.o : pipe.c + $(GCC) $(CCFLAG) -o $@ $< + clean : -rm *.o diff --git a/fs/inode.c b/fs/inode.c index 0d895095f2d1952af5ce329d4a21021bace4c9cd..85395a915dad62de9c5509d8d52e0065949543cb 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -203,6 +203,23 @@ struct m_inode * get_empty_inode() { return inode; } +struct m_inode * get_pipe_inode() { + struct m_inode * inode; + + if (!(inode = get_empty_inode())) + return NULL; + + if (!(inode->i_size = get_free_page())) { + inode->i_count = 0; + return NULL; + } + + inode->i_count = 2; + PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0; + inode->i_pipe = 1; + return inode; +} + struct m_inode * iget(int dev, int nr) { struct m_inode * inode, * empty; if (!dev) diff --git a/fs/pipe.c b/fs/pipe.c new file mode 100644 index 0000000000000000000000000000000000000000..2f40694aae6951ec2563d89b394fc65781e48214 --- /dev/null +++ b/fs/pipe.c @@ -0,0 +1,118 @@ +#include +#include +#include + +#include +#include +#include +#include + +int read_pipe(struct m_inode * inode, char * buf, int count) { + int chars, size, read = 0; + + while (count>0) { + while (!(size=PIPE_SIZE(*inode))) { + wake_up(& PIPE_WRITE_WAIT(*inode)); + if (inode->i_count != 2) + return read; + if (current->signal & ~current->blocked) + return read?read:-ERESTARTSYS; + interruptible_sleep_on(& PIPE_READ_WAIT(*inode)); + } + + chars = PAGE_SIZE-PIPE_TAIL(*inode); + if (chars > count) + chars = count; + if (chars > size) + chars = size; + count -= chars; + read += chars; + size = PIPE_TAIL(*inode); + PIPE_TAIL(*inode) += chars; + PIPE_TAIL(*inode) &= (PAGE_SIZE-1); + while (chars-->0) + put_fs_byte(((char *)inode->i_size)[size++],buf++); + } + + wake_up(& PIPE_WRITE_WAIT(*inode)); + return read; +} + +int write_pipe(struct m_inode * inode, char * buf, int count) { + int chars, size, written = 0; + + while (count>0) { + while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) { + wake_up(& PIPE_READ_WAIT(*inode)); + if (inode->i_count != 2) { + current->signal |= (1<<(SIGPIPE-1)); + return written?written:-1; + } + sleep_on(& PIPE_WRITE_WAIT(*inode)); + } + + chars = PAGE_SIZE-PIPE_HEAD(*inode); + if (chars > count) + chars = count; + if (chars > size) + chars = size; + count -= chars; + written += chars; + size = PIPE_HEAD(*inode); + PIPE_HEAD(*inode) += chars; + PIPE_HEAD(*inode) &= (PAGE_SIZE-1); + while (chars-->0) + ((char *)inode->i_size)[size++]=get_fs_byte(buf++); + } + wake_up(& PIPE_READ_WAIT(*inode)); + return written; +} + +int sys_pipe(unsigned long * fildes) { + struct m_inode * inode; + struct file * f[2]; + int fd[2]; + int i,j; + + j=0; + for(i=0;j<2 && if_count++; + } + + if (j==1) + f[0]->f_count=0; + if (j<2) + return -1; + + j=0; + for(i=0;j<2 && ifilp[i]) { + current->filp[ fd[j]=i ] = f[j]; + j++; + } + } + + if (j==1) + current->filp[fd[0]]=NULL; + if (j<2) { + f[0]->f_count=f[1]->f_count=0; + return -1; + } + + if (!(inode = get_pipe_inode())) { + current->filp[fd[0]] = + current->filp[fd[1]] = NULL; + f[0]->f_count = f[1]->f_count = 0; + return -1; + } + + f[0]->f_inode = f[1]->f_inode = inode; + f[0]->f_pos = f[1]->f_pos = 0; + f[0]->f_mode = 1; + f[1]->f_mode = 2; + put_fs_long(fd[0],0+fildes); + put_fs_long(fd[1],1+fildes); + return 0; +} + diff --git a/fs/read_write.c b/fs/read_write.c index cf2c111dfd7465c690d3cb5e1f01cd0d3d0ac980..5c02ac7b71585794d48883c1fa3a32cdcbe02c30 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -6,6 +6,8 @@ #include extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos); +extern int read_pipe(struct m_inode * inode, char * buf, int count); +extern int write_pipe(struct m_inode * inode, char * buf, int count); extern int file_read(struct m_inode * inode, struct file * filp, char * buf, int count); @@ -49,6 +51,9 @@ int sys_read(unsigned int fd,char * buf,int count) { verify_area(buf,count); inode = file->f_inode; + if (inode->i_pipe) { + return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO; + } if (S_ISCHR(inode->i_mode)) { return rw_char(READ, inode->i_zone[0], buf, count, &file->f_pos); } @@ -77,6 +82,9 @@ int sys_write(unsigned int fd,char * buf,int count) { inode=file->f_inode; + if (inode->i_pipe) { + return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO; + } if (S_ISCHR(inode->i_mode)) { return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos); } diff --git a/include/linux/fs.h b/include/linux/fs.h index 808ad323c872dd5939192e13a69fd154ea3c44bd..888b4793acabd51812ce2d5ef87f0d4841bb3777 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -37,6 +37,14 @@ void buffer_init(long buffer_end); #define INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct d_inode))) #define DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct dir_entry))) +#define PIPE_READ_WAIT(inode) ((inode).i_wait) +#define PIPE_WRITE_WAIT(inode) ((inode).i_wait2) +#define PIPE_HEAD(inode) ((inode).i_zone[0]) +#define PIPE_TAIL(inode) ((inode).i_zone[1]) +#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1)) +#define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode)) +#define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1)) + struct buffer_head { char * b_data; unsigned long b_blocknr; diff --git a/include/linux/sys.h b/include/linux/sys.h index 74b07191b9cc50eff9d560d9e4621dfc33b64a42..baad2a428a3e8269e92971f51f4cb16b4472357a 100644 --- a/include/linux/sys.h +++ b/include/linux/sys.h @@ -40,7 +40,7 @@ extern int sys_rename(); extern int sys_mkdir(); extern int sys_rmdir(); extern int sys_dup(); -//extern int sys_pipe(); +extern int sys_pipe(); //extern int sys_times(); extern int sys_prof(); extern int sys_brk(); @@ -135,7 +135,7 @@ fn_ptr sys_call_table[] = { sys_rmdir, sys_dup, - 0, // sys_pipe, + sys_pipe, 0, // sys_times, sys_prof, sys_brk,