--- linux/fs/pipe.c 2018/04/24 18:02:43 1.1.1.3 +++ linux/fs/pipe.c 2018/04/24 18:08:38 1.1.1.7 @@ -7,25 +7,27 @@ #include #include #include +#include -#include -#include /* for get_free_page */ #include + +#include #include -int read_pipe(struct m_inode * inode, char * buf, int count) +static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count) { int chars, size, read = 0; - while (count>0) { - while (!(size=PIPE_SIZE(*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 read; + return 0; if (current->signal & ~current->blocked) - return read?read:-ERESTARTSYS; + 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; @@ -40,21 +42,27 @@ int read_pipe(struct m_inode * inode, ch put_fs_byte(((char *)inode->i_size)[size++],buf++); } wake_up(& PIPE_WRITE_WAIT(*inode)); - return read; + return read?read:-EAGAIN; } -int write_pipe(struct m_inode * inode, char * buf, int count) +static int pipe_write(struct inode * inode, struct file * filp, char * buf, int count) { int chars, size, written = 0; + if (inode->i_count != 2) { /* no readers */ + send_sig(SIGPIPE,current,0); + return -EINTR; + } 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 written?written:-1; + send_sig(SIGPIPE,current,0); + return written?written:-EINTR; } - sleep_on(& PIPE_WRITE_WAIT(*inode)); + if (current->signal & ~current->blocked) + return written?written:-EINTR; + interruptible_sleep_on(&PIPE_WRITE_WAIT(*inode)); } chars = PAGE_SIZE-PIPE_HEAD(*inode); if (chars > count) @@ -73,13 +81,76 @@ int write_pipe(struct m_inode * inode, c return written; } +static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig) +{ + return -ESPIPE; +} + +static int pipe_readdir(struct inode * inode, struct file * file, struct dirent * de, int count) +{ + return -ENOTDIR; +} + +static int bad_pipe_rw(struct inode * inode, struct file * filp, char * buf, int count) +{ + return -EBADF; +} + +static int pipe_ioctl(struct inode *pino, struct file * filp, + unsigned int cmd, unsigned 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; + } +} + +/* + * Ok, these two routines should keep track of readers/writers, + * but it's currently done with the inode->i_count checking. + */ +static void pipe_read_release(struct inode * inode, struct file * filp) +{ +} + +static void pipe_write_release(struct inode * inode, struct file * filp) +{ +} + +static struct file_operations read_pipe_fops = { + pipe_lseek, + pipe_read, + bad_pipe_rw, + pipe_readdir, + NULL, /* pipe_select */ + pipe_ioctl, + NULL, /* no special open code */ + pipe_read_release +}; + +static struct file_operations write_pipe_fops = { + pipe_lseek, + bad_pipe_rw, + pipe_write, + pipe_readdir, + NULL, /* pipe_select */ + pipe_ioctl, + NULL, /* no special open code */ + pipe_write_release +}; + int sys_pipe(unsigned long * fildes) { - struct m_inode * inode; + struct inode * inode; struct file * f[2]; int fd[2]; int i,j; + verify_area(fildes,8); j=0; for(i=0;j<2 && if_inode = f[1]->f_inode = inode; f[0]->f_pos = f[1]->f_pos = 0; + f[0]->f_flags = f[1]->f_flags = 0; + f[0]->f_op = &read_pipe_fops; f[0]->f_mode = 1; /* read */ + f[1]->f_op = &write_pipe_fops; f[1]->f_mode = 2; /* write */ put_fs_long(fd[0],0+fildes); put_fs_long(fd[1],1+fildes); return 0; } - -int pipe_ioctl(struct m_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; - } -}