Index: fs/pipe.c =================================================================== RCS file: /vger/linux/fs/pipe.c,v retrieving revision 1.36 diff -u -r1.36 pipe.c --- pipe.c 1998/03/27 07:01:11 1.36 +++ pipe.c 1998/04/25 14:49:01 @@ -37,7 +37,7 @@ size_t count, loff_t *ppos) { struct inode * inode = filp->f_dentry->d_inode; - ssize_t chars = 0, size = 0, read = 0; + ssize_t chars = 0, size = 0, read = 0, ret = 0; char *pipebuf; if (ppos != &filp->f_pos) @@ -68,31 +68,36 @@ chars = count; if (chars > size) chars = size; - read += chars; pipebuf = PIPE_BASE(*inode)+PIPE_START(*inode); + if (copy_to_user(buf, pipebuf, chars )) { + ret = -EFAULT; + goto out; + } + read += chars; PIPE_START(*inode) += chars; PIPE_START(*inode) &= (PIPE_BUF-1); PIPE_LEN(*inode) -= chars; count -= chars; - copy_to_user(buf, pipebuf, chars ); buf += chars; } + ret = read; + if (!read && PIPE_WRITERS(*inode)) + ret = -EAGAIN; + out: PIPE_LOCK(*inode)--; - wake_up_interruptible(&PIPE_WAIT(*inode)); if (read) { + wake_up_interruptible(&PIPE_WAIT(*inode)); UPDATE_ATIME(inode); - return read; } - if (PIPE_WRITERS(*inode)) - return -EAGAIN; - return 0; + + return ret; } static ssize_t pipe_write(struct file * filp, const char * buf, size_t count, loff_t *ppos) { struct inode * inode = filp->f_dentry->d_inode; - ssize_t chars = 0, free = 0, written = 0; + ssize_t chars = 0, free = 0, written = 0, ret = 0; char *pipebuf; if (ppos != &filp->f_pos) @@ -127,19 +132,29 @@ if (chars > free) chars = free; pipebuf = PIPE_BASE(*inode)+PIPE_END(*inode); + if (copy_from_user(pipebuf, buf, chars )) { + ret = -EFAULT; + PIPE_LOCK(*inode)--; + goto out; + } written += chars; PIPE_LEN(*inode) += chars; count -= chars; - copy_from_user(pipebuf, buf, chars ); buf += chars; } PIPE_LOCK(*inode)--; wake_up_interruptible(&PIPE_WAIT(*inode)); free = 1; + } + ret = written; + out: + if (written) { + inode->i_ctime = inode->i_mtime = CURRENT_TIME; + mark_inode_dirty(inode); + if (ret != written) + wake_up_interruptible(&PIPE_WAIT(*inode)); } - inode->i_ctime = inode->i_mtime = CURRENT_TIME; - mark_inode_dirty(inode); - return written; + return ret; } static long long pipe_lseek(struct file * file, long long offset, int orig)