Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
struct inode *get_pipe_inode(void)
{
    register struct inode *inode;
    extern struct inode_operations pipe_inode_operations;

    if ((inode = get_empty_inode())) {
	if (!(PIPE_BASE(*inode) = get_pipe_mem())) {
	    iput(inode);
	    return NULL;
	}
	inode->i_op = &pipe_inode_operations;
	inode->i_count = 2;	/* sum of readers/writers */
	PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
	PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
	PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
	PIPE_LOCK(*inode) = 0;
	inode->i_pipe = 1;
	inode->i_mode |= S_IFIFO | S_IRUSR | S_IWUSR;
	inode->i_uid = current->euid;
	inode->i_gid = (__u8) current->egid;
	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;

#if 0
	inode->i_blksize = PAGE_SIZE;
#endif

    }
    return inode;
}
Beispiel #4
0
struct inode* pipe_new(struct inode* inode)
{
    unsigned long page;

    page = __get_free_page(GFP_USER);
    if (!page)
        return NULL;

    inode->i_pipe = kmalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
    if (!inode->i_pipe)
        goto fail_page;

    init_waitqueue_head(PIPE_WAIT(*inode));
    PIPE_BASE(*inode) = (char*) page;
    PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
    PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
    PIPE_WAITING_WRITERS(*inode) = 0;
    PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1;
    *PIPE_FASYNC_READERS(*inode) = *PIPE_FASYNC_WRITERS(*inode) = NULL;

    return inode;
fail_page:
    free_page(page);
    return NULL;
}
Beispiel #5
0
static struct inode * get_pipe_inode(void)
{
	extern struct inode_operations pipe_inode_operations;
	struct inode *inode = get_empty_inode();

	if (inode) {
		unsigned long page = __get_free_page(GFP_USER);

		if (!page) {
			iput(inode);
			inode = NULL;
		} else {
			PIPE_BASE(*inode) = (char *) page;
			inode->i_op = &pipe_inode_operations;
			PIPE_WAIT(*inode) = NULL;
			PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
			PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
			PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
			PIPE_LOCK(*inode) = 0;
			/*
			 * Mark the inode dirty from the very beginning,
			 * that way it will never be moved to the dirty
			 * list because "mark_inode_dirty()" will think
			 * that it already _is_ on the dirty list.
			 */
			inode->i_state = I_DIRTY;
			inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR;
			inode->i_uid = current->fsuid;
			inode->i_gid = current->fsgid;
			inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
			inode->i_blksize = PAGE_SIZE;
		}
	}
	return inode;
}
Beispiel #6
0
void init_fifo(struct inode * inode)
{
	inode->i_op = &fifo_inode_operations;
	inode->i_pipe = 1;
	PIPE_LOCK(*inode) = 0;
	PIPE_BASE(*inode) = NULL;
	PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
	PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
	PIPE_WAIT(*inode) = NULL;
	PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
}
Beispiel #7
0
static int pipe_rdwr_open(register struct inode *inode,
			  register struct file *filp)
{
    debug("PIPE: rdwr called.\n");

    if(!PIPE_BASE(*inode)) {
	if(!(PIPE_BASE(*inode) = get_pipe_mem()))
	    return -ENOMEM;
#if 0
	/* next fields already set to zero by get_empty_inode() */
	PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
	PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
	PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
	PIPE_LOCK(*inode) = 0;
#endif
    }
    if (filp->f_mode & FMODE_READ) {
	(inode->u.pipe_i.readers)++;
	if(inode->u.pipe_i.writers > 0) {
	    if(inode->u.pipe_i.readers < 2)
		wake_up_interruptible(&(inode->u.pipe_i.wait));
	}
	else {
	    if(!(filp->f_flags & O_NONBLOCK) && (inode->i_sb))
		while(!(inode->u.pipe_i.writers))
		    interruptible_sleep_on(&(inode->u.pipe_i.wait));
	}
    }

    if (filp->f_mode & FMODE_WRITE) {
	(inode->u.pipe_i.writers)++;
	if(inode->u.pipe_i.readers > 0) {
	    if(inode->u.pipe_i.writers < 2)
		wake_up_interruptible(&(inode->u.pipe_i.wait));
	}
	else {
	    if(filp->f_flags & O_NONBLOCK)
		return -ENXIO;
	    while(!(inode->u.pipe_i.readers))
		interruptible_sleep_on(&(inode->u.pipe_i.wait));
	}
    }
    return 0;
}
Beispiel #8
0
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 size, read, ret;

	/* Seeks are not allowed on pipes.  */
	ret = -ESPIPE;
	read = 0;
	if (ppos != &filp->f_pos)
		goto out_nolock;

	/* Always return 0 on null read.  */
	ret = 0;
	if (count == 0)
		goto out_nolock;

	/* Get the pipe semaphore */
	ret = -ERESTARTSYS;
	if (down_interruptible(PIPE_SEM(*inode)))
		goto out_nolock;

	if (PIPE_EMPTY(*inode)) {
do_more_read:
		ret = 0;
		if (!PIPE_WRITERS(*inode))
			goto out;

		ret = -EAGAIN;
		if (filp->f_flags & O_NONBLOCK)
			goto out;

		for (;;) {
			PIPE_WAITING_READERS(*inode)++;
			pipe_wait(inode);
			PIPE_WAITING_READERS(*inode)--;
			ret = -ERESTARTSYS;
			if (signal_pending(current))
				goto out;
			ret = 0;
			if (!PIPE_EMPTY(*inode))
				break;
			if (!PIPE_WRITERS(*inode))
				goto out;
		}
	}

	/* Read what data is available.  */
	ret = -EFAULT;
	while (count > 0 && (size = PIPE_LEN(*inode))) {
		char *pipebuf = PIPE_BASE(*inode) + PIPE_START(*inode);
		ssize_t chars = PIPE_MAX_RCHUNK(*inode);

		if (chars > count)
			chars = count;
		if (chars > size)
			chars = size;

		if (copy_to_user(buf, pipebuf, chars))
			goto out;

		read += chars;
		PIPE_START(*inode) += chars;
		PIPE_START(*inode) &= (PIPE_SIZE - 1);
		PIPE_LEN(*inode) -= chars;
		count -= chars;
		buf += chars;
	}

	/* Cache behaviour optimization */
	if (!PIPE_LEN(*inode))
		PIPE_START(*inode) = 0;

	if (count && PIPE_WAITING_WRITERS(*inode) && !(filp->f_flags & O_NONBLOCK)) {
		/*
		 * We know that we are going to sleep: signal
		 * writers synchronously that there is more
		 * room.
		 */
		wake_up_interruptible_sync(PIPE_WAIT(*inode));
		if (!PIPE_EMPTY(*inode))
			BUG();
		goto do_more_read;
	}
	/* Signal writers asynchronously that there is more room.  */
	wake_up_interruptible(PIPE_WAIT(*inode));

	ret = read;
out:
	up(PIPE_SEM(*inode));
out_nolock:
	if (read)
		ret = read;

	UPDATE_ATIME(inode);
	return ret;
}
Beispiel #9
0
static ssize_t
pipe_readv(struct file *filp, const struct iovec *_iov,
           unsigned long nr_segs, loff_t *ppos)
{
    struct inode *inode = filp->f_dentry->d_inode;
    int do_wakeup;
    ssize_t ret;
    struct iovec *iov = (struct iovec *)_iov;
    size_t total_len;

    total_len = iov_length(iov, nr_segs);
    /* Null read succeeds. */
    if (unlikely(total_len == 0))
        return 0;

    do_wakeup = 0;
    ret = 0;
    down(PIPE_SEM(*inode));
    for (;;) {
        int size = PIPE_LEN(*inode);
        if (size) {
            char *pipebuf = PIPE_BASE(*inode) + PIPE_START(*inode);
            ssize_t chars = PIPE_MAX_RCHUNK(*inode);

            if (chars > total_len)
                chars = total_len;
            if (chars > size)
                chars = size;

            if (pipe_iov_copy_to_user(iov, pipebuf, chars)) {
                if (!ret) ret = -EFAULT;
                break;
            }
            ret += chars;

            PIPE_START(*inode) += chars;
            PIPE_START(*inode) &= (PIPE_SIZE - 1);
            PIPE_LEN(*inode) -= chars;
            total_len -= chars;
            do_wakeup = 1;
            if (!total_len)
                break;	/* common path: read succeeded */
        }
        if (PIPE_LEN(*inode)) /* test for cyclic buffers */
            continue;
        if (!PIPE_WRITERS(*inode))
            break;
        if (!PIPE_WAITING_WRITERS(*inode)) {
            /* syscall merging: Usually we must not sleep
             * if O_NONBLOCK is set, or if we got some data.
             * But if a writer sleeps in kernel space, then
             * we can wait for that data without violating POSIX.
             */
            if (ret)
                break;
            if (filp->f_flags & O_NONBLOCK) {
                ret = -EAGAIN;
                break;
            }
        }
        if (signal_pending(current)) {
            if (!ret) ret = -ERESTARTSYS;
            break;
        }
        if (do_wakeup) {
            wake_up_interruptible_sync(PIPE_WAIT(*inode));
            kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
        }
        pipe_wait(inode);
    }
    up(PIPE_SEM(*inode));
    /* Signal writers asynchronously that there is more room.  */
    if (do_wakeup) {
        wake_up_interruptible(PIPE_WAIT(*inode));
        kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
    }
    /*
     * Hack: we turn off atime updates for -RT kernels.
     * Who uses them on pipes anyway?
     */
#ifndef CONFIG_PREEMPT_RT
    if (ret > 0)
        file_accessed(filp);
#endif
    return ret;
}
Beispiel #10
0
static int fifo_open(struct inode * inode,struct file * filp)
{
	int retval = 0;
	unsigned long page;

	switch( filp->f_mode ) {

	case 1:
	/*
	 *  O_RDONLY
	 *  POSIX.1 says that O_NONBLOCK means return with the FIFO
	 *  opened, even when there is no process writing the FIFO.
	 */
		filp->f_op = &connecting_fifo_fops;
		if (!PIPE_READERS(*inode)++)
			wake_up_interruptible(&PIPE_WAIT(*inode));
		if (!(filp->f_flags & O_NONBLOCK) && !PIPE_WRITERS(*inode)) {
			PIPE_RD_OPENERS(*inode)++;
			while (!PIPE_WRITERS(*inode)) {
				if (current->signal & ~current->blocked) {
					retval = -ERESTARTSYS;
					break;
				}
				interruptible_sleep_on(&PIPE_WAIT(*inode));
			}
			if (!--PIPE_RD_OPENERS(*inode))
				wake_up_interruptible(&PIPE_WAIT(*inode));
		}
		while (PIPE_WR_OPENERS(*inode))
			interruptible_sleep_on(&PIPE_WAIT(*inode));
		if (PIPE_WRITERS(*inode))
			filp->f_op = &read_fifo_fops;
		if (retval && !--PIPE_READERS(*inode))
			wake_up_interruptible(&PIPE_WAIT(*inode));
		break;
	
	case 2:
	/*
	 *  O_WRONLY
	 *  POSIX.1 says that O_NONBLOCK means return -1 with
	 *  errno=ENXIO when there is no process reading the FIFO.
	 */
		if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode)) {
			retval = -ENXIO;
			break;
		}
		filp->f_op = &write_fifo_fops;
		if (!PIPE_WRITERS(*inode)++)
			wake_up_interruptible(&PIPE_WAIT(*inode));
		if (!PIPE_READERS(*inode)) {
			PIPE_WR_OPENERS(*inode)++;
			while (!PIPE_READERS(*inode)) {
				if (current->signal & ~current->blocked) {
					retval = -ERESTARTSYS;
					break;
				}
				interruptible_sleep_on(&PIPE_WAIT(*inode));
			}
			if (!--PIPE_WR_OPENERS(*inode))
				wake_up_interruptible(&PIPE_WAIT(*inode));
		}
		while (PIPE_RD_OPENERS(*inode))
			interruptible_sleep_on(&PIPE_WAIT(*inode));
		if (retval && !--PIPE_WRITERS(*inode))
			wake_up_interruptible(&PIPE_WAIT(*inode));
		break;
	
	case 3:
	/*
	 *  O_RDWR
	 *  POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
	 *  This implementation will NEVER block on a O_RDWR open, since
	 *  the process can at least talk to itself.
	 */
		filp->f_op = &rdwr_fifo_fops;
		if (!PIPE_READERS(*inode)++)
			wake_up_interruptible(&PIPE_WAIT(*inode));
		while (PIPE_WR_OPENERS(*inode))
			interruptible_sleep_on(&PIPE_WAIT(*inode));
		if (!PIPE_WRITERS(*inode)++)
			wake_up_interruptible(&PIPE_WAIT(*inode));
		while (PIPE_RD_OPENERS(*inode))
			interruptible_sleep_on(&PIPE_WAIT(*inode));
		break;

	default:
		retval = -EINVAL;
	}
	if (retval || PIPE_BASE(*inode))
		return retval;
	page = __get_free_page(GFP_KERNEL);
	if (PIPE_BASE(*inode)) {
		free_page(page);
		return 0;
	}
	if (!page)
		return -ENOMEM;
	PIPE_LOCK(*inode) = 0;
	PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
	PIPE_BASE(*inode) = (char *) page;
	return 0;
}