--- linux/fs/pipe.c 2018/04/24 18:00:41 1.1.1.1 +++ linux/fs/pipe.c 2018/04/24 18:03:41 1.1.1.4 @@ -1,57 +1,84 @@ +/* + * linux/fs/pipe.c + * + * (C) 1991 Linus Torvalds + */ + #include +#include +#include +#include #include -#include /* for get_free_page */ #include +#include -int read_pipe(struct m_inode * inode, char * buf, int count) +int pipe_read(struct inode * inode, struct file * filp, char * buf, int count) { - char * b=buf; + int chars, size, read = 0; - while (PIPE_EMPTY(*inode)) { - wake_up(&inode->i_wait); - if (inode->i_count != 2) /* are there any writers left? */ - return 0; - sleep_on(&inode->i_wait); - } - while (count>0 && !(PIPE_EMPTY(*inode))) { - count --; - put_fs_byte(((char *)inode->i_size)[PIPE_TAIL(*inode)],b++); - INC_PIPE( PIPE_TAIL(*inode) ); + if (!(filp->f_flags & O_NONBLOCK)) + while (!PIPE_SIZE(*inode)) { + wake_up(& PIPE_WRITE_WAIT(*inode)); + if (inode->i_count != 2) /* are there any writers? */ + return 0; + if (current->signal & ~current->blocked) + return -ERESTARTSYS; + interruptible_sleep_on(& PIPE_READ_WAIT(*inode)); + } + while (count>0 && (size = PIPE_SIZE(*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(&inode->i_wait); - return b-buf; + wake_up(& PIPE_WRITE_WAIT(*inode)); + return read; } -int write_pipe(struct m_inode * inode, char * buf, int count) +int pipe_write(struct inode * inode, struct file * filp, char * buf, int count) { - char * b=buf; + int chars, size, written = 0; - wake_up(&inode->i_wait); - if (inode->i_count != 2) { /* no readers */ - current->signal |= (1<<(SIGPIPE-1)); - return -1; - } - while (count-->0) { - while (PIPE_FULL(*inode)) { - wake_up(&inode->i_wait); - if (inode->i_count != 2) { + while (count>0) { + while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) { + wake_up(& PIPE_READ_WAIT(*inode)); + if (inode->i_count != 2) { /* no readers */ current->signal |= (1<<(SIGPIPE-1)); - return b-buf; + return written?written:-EINTR; } - sleep_on(&inode->i_wait); + if (current->signal & ~current->blocked) + return written?written:-EINTR; + interruptible_sleep_on(&PIPE_WRITE_WAIT(*inode)); } - ((char *)inode->i_size)[PIPE_HEAD(*inode)] = get_fs_byte(b++); - INC_PIPE( PIPE_HEAD(*inode) ); - wake_up(&inode->i_wait); + 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(&inode->i_wait); - return b-buf; + wake_up(& PIPE_READ_WAIT(*inode)); + return written; } int sys_pipe(unsigned long * fildes) { - struct m_inode * inode; + struct inode * inode; struct file * f[2]; int fd[2]; int i,j; @@ -90,3 +117,15 @@ int sys_pipe(unsigned long * fildes) put_fs_long(fd[1],1+fildes); return 0; } + +int pipe_ioctl(struct inode *pino, int cmd, int arg) +{ + switch (cmd) { + case FIONREAD: + verify_area((void *) arg,4); + put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg); + return 0; + default: + return -EINVAL; + } +}