/* * linux/fs/pipe.c * * (C) 1991 Linus Torvalds */ #include #include #include /* for get_free_page */ #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(&inode->i_wait); if (inode->i_count != 2) /* are there any writers? */ return read; sleep_on(&inode->i_wait); } 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 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(&inode->i_wait); if (inode->i_count != 2) { /* no readers */ current->signal |= (1 << (SIGPIPE - 1)); return written ? written : -1; } sleep_on(&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 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 && i < NR_FILE; i++) if (!file_table[i].f_count) (f[j++] = i + file_table)->f_count++; if (j == 1) f[0]->f_count = 0; if (j < 2) return -1; j = 0; for (i = 0; j < 2 && i < NR_OPEN; i++) if (!current->filp[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; /* read */ f[1]->f_mode = 2; /* write */ put_fs_long(fd[0], 0 + fildes); put_fs_long(fd[1], 1 + fildes); return 0; } int sys_pipe2(int fd[2], int flags) { if (flags == 0) { sys_pipe(fd); } return 0; }