int PipeRead(struct File* file, BYTE* buffer, DWORD count) { DWORD size = 0, chars = 0; int read = 0; if (!count) return 0; if (file->flags & FILE_NONBLOCK) { if (PIPE_LOCK(file)) return 0; // if (PIPE_EMPTY(file)) // { /* return -EAGAIN? */ // return 0; // } }else{ while (PIPE_EMPTY(file) || PIPE_LOCK(file)) { if (PIPE_EMPTY(file)) return 0; KePrint("WAIT\n"); // WAIT_ON(&PIPE_WAIT(file), (PIPE_LOCK(file) == 0)); } } PIPE_LOCK(file)++; while (count > 0 && (size = PIPE_SIZE(file))) { char* pipeBuf = PIPE_BUF(file) + PIPE_START(file); chars = PIPE_MAX_RCHUNK(file); if (chars > count) chars = count; if (chars > size) chars = size; read += chars; PIPE_START(file) += chars; PIPE_START(file) &= (PIPE_BUFFER_SIZE - 1); PIPE_SIZE(file) -= chars; count -= chars; memcpy(buffer, pipeBuf, chars); buffer+=chars; } PIPE_LOCK(file)--; WakeUp(&PIPE_WAIT(file)); 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 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; }
static ssize_t pipe_read(struct file * filp, char * buf, size_t count, loff_t *ppos) { struct inode * inode = filp->f_dentry->d_inode; ssize_t chars = 0, size = 0, read = 0; char *pipebuf; if (ppos != &filp->f_pos) return -ESPIPE; if ( !count ) return 0; if (filp->f_flags & O_NONBLOCK) { if (PIPE_LOCK(*inode)) return -EAGAIN; if (PIPE_EMPTY(*inode)) { if (PIPE_WRITERS(*inode)) return -EAGAIN; else return 0; } } else while (PIPE_EMPTY(*inode) || PIPE_LOCK(*inode)) { if (PIPE_EMPTY(*inode)) { if (!PIPE_WRITERS(*inode) || !count) return 0; } if (signal_pending(current)) return -ERESTARTSYS; interruptible_sleep_on(&PIPE_WAIT(*inode)); } PIPE_LOCK(*inode)++; while (count>0 && (size = PIPE_SIZE(*inode))) { chars = PIPE_MAX_RCHUNK(*inode); if (chars > count) chars = count; if (chars > size) chars = size; read += chars; pipebuf = PIPE_BASE(*inode)+PIPE_START(*inode); PIPE_START(*inode) += chars; PIPE_START(*inode) &= (PIPE_BUF-1); PIPE_LEN(*inode) -= chars; count -= chars; copy_to_user(buf, pipebuf, chars ); buf += chars; } PIPE_LOCK(*inode)--; wake_up_interruptible(&PIPE_WAIT(*inode)); if (read) { UPDATE_ATIME(inode); return read; } if (PIPE_WRITERS(*inode)) return -EAGAIN; return 0; }
static void cp_new_stat(struct inode * inode, struct new_stat * statbuf) { struct new_stat tmp; unsigned int blocks, indirect; memset(&tmp, 0, sizeof(tmp)); tmp.st_dev = kdev_t_to_nr(inode->i_dev); tmp.st_ino = inode->i_ino; tmp.st_mode = inode->i_mode; tmp.st_nlink = inode->i_nlink; tmp.st_uid = inode->i_uid; tmp.st_gid = inode->i_gid; tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); tmp.st_size = inode->i_size; if (inode->i_pipe) tmp.st_size = PIPE_SIZE(*inode); tmp.st_atime = inode->i_atime; tmp.st_mtime = inode->i_mtime; tmp.st_ctime = inode->i_ctime; /* * st_blocks and st_blksize are approximated with a simple algorithm if * they aren't supported directly by the filesystem. The minix and msdos * filesystems don't keep track of blocks, so they would either have to * be counted explicitly (by delving into the file itself), or by using * this simple algorithm to get a reasonable (although not 100% accurate) * value. */ /* * Use minix fs values for the number of direct and indirect blocks. The * count is now exact for the minix fs except that it counts zero blocks. * Everything is in BLOCK_SIZE'd units until the assignment to * tmp.st_blksize. */ #define D_B 7 #define I_B (BLOCK_SIZE / sizeof(unsigned short)) if (!inode->i_blksize) { blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE; if (blocks > D_B) { indirect = (blocks - D_B + I_B - 1) / I_B; blocks += indirect; if (indirect > 1) { indirect = (indirect - 1 + I_B - 1) / I_B; blocks += indirect; if (indirect > 1) blocks++; } } tmp.st_blocks = (BLOCK_SIZE / 512) * blocks; tmp.st_blksize = BLOCK_SIZE; } else { tmp.st_blocks = inode->i_blocks; tmp.st_blksize = inode->i_blksize; } memcpy_tofs(statbuf,&tmp,sizeof(tmp)); }
static int pipe_ioctl(struct inode *pino, struct file * filp, unsigned int cmd, unsigned long arg) { switch (cmd) { case FIONREAD: return put_user(PIPE_SIZE(*pino),(int *) arg); default: return -EINVAL; } }
int PipePoll(struct File* file, struct PollItem* item, struct PollQueue* pollQueue) { int mask = 0; if (file->vNode->mode & VFS_ATTR_READ) { if (PIPE_SIZE(file) > 0) item->revents = POLL_IN; } if (file->vNode->mode & VFS_ATTR_WRITE) { if (PIPE_MAX_WCHUNK(file) > 0) item->revents = POLL_OUT; } PollAddWait(pollQueue, &PIPE_WAIT(file)); return mask; }
/* * For backward compatibility? Maybe this should be moved * into arch/i386 instead? */ static void cp_old_stat(struct inode * inode, struct old_stat * statbuf) { struct old_stat tmp; printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n", current->comm); tmp.st_dev = kdev_t_to_nr(inode->i_dev); tmp.st_ino = inode->i_ino; tmp.st_mode = inode->i_mode; tmp.st_nlink = inode->i_nlink; tmp.st_uid = inode->i_uid; tmp.st_gid = inode->i_gid; tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); tmp.st_size = inode->i_size; if (inode->i_pipe) tmp.st_size = PIPE_SIZE(*inode); tmp.st_atime = inode->i_atime; tmp.st_mtime = inode->i_mtime; tmp.st_ctime = inode->i_ctime; memcpy_tofs(statbuf,&tmp,sizeof(tmp)); }
int PipeWrite(struct File* file,BYTE* buffer,DWORD size) { DWORD free = 0, chars; int written = 0; int err = 0; /* If we've got no readers on this pipe, let userspace know. */ if (PIPE_READERS(file) == 0) return -EPIPE; if (size <= PIPE_BUFFER_SIZE) free = size; else free = 1; while (size > 0) { while ((PIPE_FREE(file) < free || PIPE_LOCK(file))) { if (!PIPE_READERS(file) == 0) { err = -EPIPE; goto out; } if (file->flags & FILE_NONBLOCK) { goto out; } WAIT_ON(&PIPE_WAIT(file), PIPE_LOCK(file) == 0); } PIPE_LOCK(file)++; while (size > 0 && (free = PIPE_FREE(file))) { char* pipeBuf = PIPE_BUF(file) + PIPE_END(file); chars = PIPE_MAX_WCHUNK(file); if (chars > size) chars = size; if (chars > free) chars = size; /* Update counters. */ written += chars; PIPE_SIZE(file) += chars; size -= chars; memcpy(pipeBuf, buffer, chars); buffer += chars; } PIPE_LOCK(file)--; WakeUp(&PIPE_WAIT(file)); free = 1; } out: return (written > 0) ? (written) : (err); }