OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [pipe.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 *  linux/fs/pipe.c
 *  linux/fs/pipe.c
 *
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */
 */
 
 
#include <asm/segment.h>
#include <asm/segment.h>
 
 
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/signal.h>
#include <linux/fcntl.h>
#include <linux/fcntl.h>
#include <linux/termios.h>
#include <linux/termios.h>
#include <linux/mm.h>
#include <linux/mm.h>
 
 
/*
/*
 * Define this if you want SunOS compatibility wrt braindead
 * Define this if you want SunOS compatibility wrt braindead
 * select behaviour on FIFO's.
 * select behaviour on FIFO's.
 */
 */
#undef FIFO_SUNOS_BRAINDAMAGE
#undef FIFO_SUNOS_BRAINDAMAGE
 
 
/* We don't use the head/tail construction any more. Now we use the start/len*/
/* We don't use the head/tail construction any more. Now we use the start/len*/
/* construction providing full use of PIPE_BUF (multiple of PAGE_SIZE) */
/* construction providing full use of PIPE_BUF (multiple of PAGE_SIZE) */
/* Florian Coosmann (FGC)                                ^ current = 1       */
/* Florian Coosmann (FGC)                                ^ current = 1       */
/* Additionally, we now use locking technique. This prevents race condition  */
/* Additionally, we now use locking technique. This prevents race condition  */
/* in case of paging and multiple read/write on the same pipe. (FGC)         */
/* in case of paging and multiple read/write on the same pipe. (FGC)         */
 
 
 
 
static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
{
{
        int chars = 0, size = 0, read = 0;
        int chars = 0, size = 0, read = 0;
        char *pipebuf;
        char *pipebuf;
 
 
        if (filp->f_flags & O_NONBLOCK) {
        if (filp->f_flags & O_NONBLOCK) {
                if (PIPE_LOCK(*inode))
                if (PIPE_LOCK(*inode))
                        return -EAGAIN;
                        return -EAGAIN;
                if (PIPE_EMPTY(*inode))
                if (PIPE_EMPTY(*inode))
                        if (PIPE_WRITERS(*inode))
                        if (PIPE_WRITERS(*inode))
                                return -EAGAIN;
                                return -EAGAIN;
                        else
                        else
                                return 0;
                                return 0;
        } else while (PIPE_EMPTY(*inode) || PIPE_LOCK(*inode)) {
        } else while (PIPE_EMPTY(*inode) || PIPE_LOCK(*inode)) {
                if (PIPE_EMPTY(*inode)) {
                if (PIPE_EMPTY(*inode)) {
                        if (!PIPE_WRITERS(*inode))
                        if (!PIPE_WRITERS(*inode))
                                return 0;
                                return 0;
                }
                }
                if (current->signal & ~current->blocked)
                if (current->signal & ~current->blocked)
                        return -ERESTARTSYS;
                        return -ERESTARTSYS;
                interruptible_sleep_on(&PIPE_WAIT(*inode));
                interruptible_sleep_on(&PIPE_WAIT(*inode));
        }
        }
        PIPE_LOCK(*inode)++;
        PIPE_LOCK(*inode)++;
        while (count>0 && (size = PIPE_SIZE(*inode))) {
        while (count>0 && (size = PIPE_SIZE(*inode))) {
                chars = PIPE_MAX_RCHUNK(*inode);
                chars = PIPE_MAX_RCHUNK(*inode);
                if (chars > count)
                if (chars > count)
                        chars = count;
                        chars = count;
                if (chars > size)
                if (chars > size)
                        chars = size;
                        chars = size;
                read += chars;
                read += chars;
                pipebuf = PIPE_BASE(*inode)+PIPE_START(*inode);
                pipebuf = PIPE_BASE(*inode)+PIPE_START(*inode);
                PIPE_START(*inode) += chars;
                PIPE_START(*inode) += chars;
                PIPE_START(*inode) &= (PIPE_BUF-1);
                PIPE_START(*inode) &= (PIPE_BUF-1);
                PIPE_LEN(*inode) -= chars;
                PIPE_LEN(*inode) -= chars;
                count -= chars;
                count -= chars;
                memcpy_tofs(buf, pipebuf, chars );
                memcpy_tofs(buf, pipebuf, chars );
                buf += chars;
                buf += chars;
        }
        }
        PIPE_LOCK(*inode)--;
        PIPE_LOCK(*inode)--;
        wake_up_interruptible(&PIPE_WAIT(*inode));
        wake_up_interruptible(&PIPE_WAIT(*inode));
        if (read) {
        if (read) {
                UPDATE_ATIME(inode);
                UPDATE_ATIME(inode);
                return read;
                return read;
        }
        }
        if (PIPE_WRITERS(*inode))
        if (PIPE_WRITERS(*inode))
                return -EAGAIN;
                return -EAGAIN;
        return 0;
        return 0;
}
}
 
 
static int pipe_write(struct inode * inode, struct file * filp, const char * buf, int count)
static int pipe_write(struct inode * inode, struct file * filp, const char * buf, int count)
{
{
        int chars = 0, free = 0, written = 0;
        int chars = 0, free = 0, written = 0;
        char *pipebuf;
        char *pipebuf;
 
 
        if (!PIPE_READERS(*inode)) { /* no readers */
        if (!PIPE_READERS(*inode)) { /* no readers */
                send_sig(SIGPIPE,current,0);
                send_sig(SIGPIPE,current,0);
                return -EPIPE;
                return -EPIPE;
        }
        }
/* if count <= PIPE_BUF, we have to make it atomic */
/* if count <= PIPE_BUF, we have to make it atomic */
        if (count <= PIPE_BUF)
        if (count <= PIPE_BUF)
                free = count;
                free = count;
        else
        else
                free = 1; /* can't do it atomically, wait for any free space */
                free = 1; /* can't do it atomically, wait for any free space */
        while (count>0) {
        while (count>0) {
                while ((PIPE_FREE(*inode) < free) || PIPE_LOCK(*inode)) {
                while ((PIPE_FREE(*inode) < free) || PIPE_LOCK(*inode)) {
                        if (!PIPE_READERS(*inode)) { /* no readers */
                        if (!PIPE_READERS(*inode)) { /* no readers */
                                send_sig(SIGPIPE,current,0);
                                send_sig(SIGPIPE,current,0);
                                return written? :-EPIPE;
                                return written? :-EPIPE;
                        }
                        }
                        if (current->signal & ~current->blocked)
                        if (current->signal & ~current->blocked)
                                return written? :-ERESTARTSYS;
                                return written? :-ERESTARTSYS;
                        if (filp->f_flags & O_NONBLOCK)
                        if (filp->f_flags & O_NONBLOCK)
                                return written? :-EAGAIN;
                                return written? :-EAGAIN;
                        interruptible_sleep_on(&PIPE_WAIT(*inode));
                        interruptible_sleep_on(&PIPE_WAIT(*inode));
                }
                }
                PIPE_LOCK(*inode)++;
                PIPE_LOCK(*inode)++;
                while (count>0 && (free = PIPE_FREE(*inode))) {
                while (count>0 && (free = PIPE_FREE(*inode))) {
                        chars = PIPE_MAX_WCHUNK(*inode);
                        chars = PIPE_MAX_WCHUNK(*inode);
                        if (chars > count)
                        if (chars > count)
                                chars = count;
                                chars = count;
                        if (chars > free)
                        if (chars > free)
                                chars = free;
                                chars = free;
                        pipebuf = PIPE_BASE(*inode)+PIPE_END(*inode);
                        pipebuf = PIPE_BASE(*inode)+PIPE_END(*inode);
                        written += chars;
                        written += chars;
                        PIPE_LEN(*inode) += chars;
                        PIPE_LEN(*inode) += chars;
                        count -= chars;
                        count -= chars;
                        memcpy_fromfs(pipebuf, buf, chars );
                        memcpy_fromfs(pipebuf, buf, chars );
                        buf += chars;
                        buf += chars;
                }
                }
                PIPE_LOCK(*inode)--;
                PIPE_LOCK(*inode)--;
                wake_up_interruptible(&PIPE_WAIT(*inode));
                wake_up_interruptible(&PIPE_WAIT(*inode));
                free = 1;
                free = 1;
        }
        }
        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
        return written;
        return written;
}
}
 
 
static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
{
{
        return -ESPIPE;
        return -ESPIPE;
}
}
 
 
static int bad_pipe_r(struct inode * inode, struct file * filp, char * buf, int count)
static int bad_pipe_r(struct inode * inode, struct file * filp, char * buf, int count)
{
{
        return -EBADF;
        return -EBADF;
}
}
 
 
static int bad_pipe_w(struct inode * inode, struct file * filp, const char * buf, int count)
static int bad_pipe_w(struct inode * inode, struct file * filp, const char * buf, int count)
{
{
        return -EBADF;
        return -EBADF;
}
}
 
 
static int pipe_ioctl(struct inode *pino, struct file * filp,
static int pipe_ioctl(struct inode *pino, struct file * filp,
        unsigned int cmd, unsigned long arg)
        unsigned int cmd, unsigned long arg)
{
{
        int error;
        int error;
 
 
        switch (cmd) {
        switch (cmd) {
                case FIONREAD:
                case FIONREAD:
                        error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
                        error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
                        if (!error)
                        if (!error)
                                put_user(PIPE_SIZE(*pino),(int *) arg);
                                put_user(PIPE_SIZE(*pino),(int *) arg);
                        return error;
                        return error;
                default:
                default:
                        return -EINVAL;
                        return -EINVAL;
        }
        }
}
}
 
 
static int pipe_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
static int pipe_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
{
{
        switch (sel_type) {
        switch (sel_type) {
                case SEL_IN:
                case SEL_IN:
                        if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode))
                        if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode))
                                return 1;
                                return 1;
                        select_wait(&PIPE_WAIT(*inode), wait);
                        select_wait(&PIPE_WAIT(*inode), wait);
                        return 0;
                        return 0;
                case SEL_OUT:
                case SEL_OUT:
                        if (PIPE_EMPTY(*inode) || !PIPE_READERS(*inode))
                        if (PIPE_EMPTY(*inode) || !PIPE_READERS(*inode))
                                return 1;
                                return 1;
                        select_wait(&PIPE_WAIT(*inode), wait);
                        select_wait(&PIPE_WAIT(*inode), wait);
                        return 0;
                        return 0;
                case SEL_EX:
                case SEL_EX:
                        if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
                        if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
                                return 1;
                                return 1;
                        select_wait(&inode->i_wait,wait);
                        select_wait(&inode->i_wait,wait);
                        return 0;
                        return 0;
        }
        }
        return 0;
        return 0;
}
}
 
 
#ifdef FIFO_SUNOS_BRAINDAMAGE
#ifdef FIFO_SUNOS_BRAINDAMAGE
/*
/*
 * Arggh. Why does SunOS have to have different select() behaviour
 * Arggh. Why does SunOS have to have different select() behaviour
 * for pipes and fifos? Hate-Hate-Hate. See difference in SEL_IN..
 * for pipes and fifos? Hate-Hate-Hate. See difference in SEL_IN..
 */
 */
static int fifo_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
static int fifo_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
{
{
        switch (sel_type) {
        switch (sel_type) {
                case SEL_IN:
                case SEL_IN:
                        if (!PIPE_EMPTY(*inode))
                        if (!PIPE_EMPTY(*inode))
                                return 1;
                                return 1;
                        select_wait(&PIPE_WAIT(*inode), wait);
                        select_wait(&PIPE_WAIT(*inode), wait);
                        return 0;
                        return 0;
                case SEL_OUT:
                case SEL_OUT:
                        if (!PIPE_FULL(*inode) || !PIPE_READERS(*inode))
                        if (!PIPE_FULL(*inode) || !PIPE_READERS(*inode))
                                return 1;
                                return 1;
                        select_wait(&PIPE_WAIT(*inode), wait);
                        select_wait(&PIPE_WAIT(*inode), wait);
                        return 0;
                        return 0;
                case SEL_EX:
                case SEL_EX:
                        if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
                        if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
                                return 1;
                                return 1;
                        select_wait(&inode->i_wait,wait);
                        select_wait(&inode->i_wait,wait);
                        return 0;
                        return 0;
        }
        }
        return 0;
        return 0;
}
}
#else
#else
 
 
#define fifo_select pipe_select
#define fifo_select pipe_select
 
 
#endif /* FIFO_SUNOS_BRAINDAMAGE */
#endif /* FIFO_SUNOS_BRAINDAMAGE */
 
 
/*
/*
 * The 'connect_xxx()' functions are needed for named pipes when
 * The 'connect_xxx()' functions are needed for named pipes when
 * the open() code hasn't guaranteed a connection (O_NONBLOCK),
 * the open() code hasn't guaranteed a connection (O_NONBLOCK),
 * and we need to act differently until we do get a writer..
 * and we need to act differently until we do get a writer..
 */
 */
static int connect_read(struct inode * inode, struct file * filp, char * buf, int count)
static int connect_read(struct inode * inode, struct file * filp, char * buf, int count)
{
{
        if (PIPE_EMPTY(*inode) && !PIPE_WRITERS(*inode))
        if (PIPE_EMPTY(*inode) && !PIPE_WRITERS(*inode))
                return 0;
                return 0;
        filp->f_op = &read_fifo_fops;
        filp->f_op = &read_fifo_fops;
        return pipe_read(inode,filp,buf,count);
        return pipe_read(inode,filp,buf,count);
}
}
 
 
static int connect_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
static int connect_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
{
{
        switch (sel_type) {
        switch (sel_type) {
                case SEL_IN:
                case SEL_IN:
                        if (!PIPE_EMPTY(*inode)) {
                        if (!PIPE_EMPTY(*inode)) {
                                filp->f_op = &read_fifo_fops;
                                filp->f_op = &read_fifo_fops;
                                return 1;
                                return 1;
                        }
                        }
                        if (PIPE_WRITERS(*inode)) {
                        if (PIPE_WRITERS(*inode)) {
                                filp->f_op = &read_fifo_fops;
                                filp->f_op = &read_fifo_fops;
                        }
                        }
                        select_wait(&PIPE_WAIT(*inode), wait);
                        select_wait(&PIPE_WAIT(*inode), wait);
                        return 0;
                        return 0;
                case SEL_OUT:
                case SEL_OUT:
                        if (!PIPE_FULL(*inode))
                        if (!PIPE_FULL(*inode))
                                return 1;
                                return 1;
                        select_wait(&PIPE_WAIT(*inode), wait);
                        select_wait(&PIPE_WAIT(*inode), wait);
                        return 0;
                        return 0;
                case SEL_EX:
                case SEL_EX:
                        if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
                        if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
                                return 1;
                                return 1;
                        select_wait(&inode->i_wait,wait);
                        select_wait(&inode->i_wait,wait);
                        return 0;
                        return 0;
        }
        }
        return 0;
        return 0;
}
}
 
 
static void pipe_read_release(struct inode * inode, struct file * filp)
static void pipe_read_release(struct inode * inode, struct file * filp)
{
{
        PIPE_READERS(*inode)--;
        PIPE_READERS(*inode)--;
        wake_up_interruptible(&PIPE_WAIT(*inode));
        wake_up_interruptible(&PIPE_WAIT(*inode));
}
}
 
 
static void pipe_write_release(struct inode * inode, struct file * filp)
static void pipe_write_release(struct inode * inode, struct file * filp)
{
{
        PIPE_WRITERS(*inode)--;
        PIPE_WRITERS(*inode)--;
        wake_up_interruptible(&PIPE_WAIT(*inode));
        wake_up_interruptible(&PIPE_WAIT(*inode));
}
}
 
 
static void pipe_rdwr_release(struct inode * inode, struct file * filp)
static void pipe_rdwr_release(struct inode * inode, struct file * filp)
{
{
        if (filp->f_mode & FMODE_READ)
        if (filp->f_mode & FMODE_READ)
                PIPE_READERS(*inode)--;
                PIPE_READERS(*inode)--;
        if (filp->f_mode & FMODE_WRITE)
        if (filp->f_mode & FMODE_WRITE)
                PIPE_WRITERS(*inode)--;
                PIPE_WRITERS(*inode)--;
        wake_up_interruptible(&PIPE_WAIT(*inode));
        wake_up_interruptible(&PIPE_WAIT(*inode));
}
}
 
 
static int pipe_read_open(struct inode * inode, struct file * filp)
static int pipe_read_open(struct inode * inode, struct file * filp)
{
{
        PIPE_READERS(*inode)++;
        PIPE_READERS(*inode)++;
        return 0;
        return 0;
}
}
 
 
static int pipe_write_open(struct inode * inode, struct file * filp)
static int pipe_write_open(struct inode * inode, struct file * filp)
{
{
        PIPE_WRITERS(*inode)++;
        PIPE_WRITERS(*inode)++;
        return 0;
        return 0;
}
}
 
 
static int pipe_rdwr_open(struct inode * inode, struct file * filp)
static int pipe_rdwr_open(struct inode * inode, struct file * filp)
{
{
        if (filp->f_mode & FMODE_READ)
        if (filp->f_mode & FMODE_READ)
                PIPE_READERS(*inode)++;
                PIPE_READERS(*inode)++;
        if (filp->f_mode & FMODE_WRITE)
        if (filp->f_mode & FMODE_WRITE)
                PIPE_WRITERS(*inode)++;
                PIPE_WRITERS(*inode)++;
        return 0;
        return 0;
}
}
 
 
/*
/*
 * The file_operations structs are not static because they
 * The file_operations structs are not static because they
 * are also used in linux/fs/fifo.c to do operations on fifo's.
 * are also used in linux/fs/fifo.c to do operations on fifo's.
 */
 */
struct file_operations connecting_fifo_fops = {
struct file_operations connecting_fifo_fops = {
        pipe_lseek,
        pipe_lseek,
        connect_read,
        connect_read,
        bad_pipe_w,
        bad_pipe_w,
        NULL,           /* no readdir */
        NULL,           /* no readdir */
        connect_select,
        connect_select,
        pipe_ioctl,
        pipe_ioctl,
        NULL,           /* no mmap on pipes.. surprise */
        NULL,           /* no mmap on pipes.. surprise */
        pipe_read_open,
        pipe_read_open,
        pipe_read_release,
        pipe_read_release,
        NULL
        NULL
};
};
 
 
struct file_operations read_fifo_fops = {
struct file_operations read_fifo_fops = {
        pipe_lseek,
        pipe_lseek,
        pipe_read,
        pipe_read,
        bad_pipe_w,
        bad_pipe_w,
        NULL,           /* no readdir */
        NULL,           /* no readdir */
        fifo_select,
        fifo_select,
        pipe_ioctl,
        pipe_ioctl,
        NULL,           /* no mmap on pipes.. surprise */
        NULL,           /* no mmap on pipes.. surprise */
        pipe_read_open,
        pipe_read_open,
        pipe_read_release,
        pipe_read_release,
        NULL
        NULL
};
};
 
 
struct file_operations write_fifo_fops = {
struct file_operations write_fifo_fops = {
        pipe_lseek,
        pipe_lseek,
        bad_pipe_r,
        bad_pipe_r,
        pipe_write,
        pipe_write,
        NULL,           /* no readdir */
        NULL,           /* no readdir */
        fifo_select,
        fifo_select,
        pipe_ioctl,
        pipe_ioctl,
        NULL,           /* mmap */
        NULL,           /* mmap */
        pipe_write_open,
        pipe_write_open,
        pipe_write_release,
        pipe_write_release,
        NULL
        NULL
};
};
 
 
struct file_operations rdwr_fifo_fops = {
struct file_operations rdwr_fifo_fops = {
        pipe_lseek,
        pipe_lseek,
        pipe_read,
        pipe_read,
        pipe_write,
        pipe_write,
        NULL,           /* no readdir */
        NULL,           /* no readdir */
        fifo_select,
        fifo_select,
        pipe_ioctl,
        pipe_ioctl,
        NULL,           /* mmap */
        NULL,           /* mmap */
        pipe_rdwr_open,
        pipe_rdwr_open,
        pipe_rdwr_release,
        pipe_rdwr_release,
        NULL
        NULL
};
};
 
 
struct file_operations read_pipe_fops = {
struct file_operations read_pipe_fops = {
        pipe_lseek,
        pipe_lseek,
        pipe_read,
        pipe_read,
        bad_pipe_w,
        bad_pipe_w,
        NULL,           /* no readdir */
        NULL,           /* no readdir */
        pipe_select,
        pipe_select,
        pipe_ioctl,
        pipe_ioctl,
        NULL,           /* no mmap on pipes.. surprise */
        NULL,           /* no mmap on pipes.. surprise */
        pipe_read_open,
        pipe_read_open,
        pipe_read_release,
        pipe_read_release,
        NULL
        NULL
};
};
 
 
struct file_operations write_pipe_fops = {
struct file_operations write_pipe_fops = {
        pipe_lseek,
        pipe_lseek,
        bad_pipe_r,
        bad_pipe_r,
        pipe_write,
        pipe_write,
        NULL,           /* no readdir */
        NULL,           /* no readdir */
        pipe_select,
        pipe_select,
        pipe_ioctl,
        pipe_ioctl,
        NULL,           /* mmap */
        NULL,           /* mmap */
        pipe_write_open,
        pipe_write_open,
        pipe_write_release,
        pipe_write_release,
        NULL
        NULL
};
};
 
 
struct file_operations rdwr_pipe_fops = {
struct file_operations rdwr_pipe_fops = {
        pipe_lseek,
        pipe_lseek,
        pipe_read,
        pipe_read,
        pipe_write,
        pipe_write,
        NULL,           /* no readdir */
        NULL,           /* no readdir */
        pipe_select,
        pipe_select,
        pipe_ioctl,
        pipe_ioctl,
        NULL,           /* mmap */
        NULL,           /* mmap */
        pipe_rdwr_open,
        pipe_rdwr_open,
        pipe_rdwr_release,
        pipe_rdwr_release,
        NULL
        NULL
};
};
 
 
struct inode_operations pipe_inode_operations = {
struct inode_operations pipe_inode_operations = {
        &rdwr_pipe_fops,
        &rdwr_pipe_fops,
        NULL,                   /* create */
        NULL,                   /* create */
        NULL,                   /* lookup */
        NULL,                   /* lookup */
        NULL,                   /* link */
        NULL,                   /* link */
        NULL,                   /* unlink */
        NULL,                   /* unlink */
        NULL,                   /* symlink */
        NULL,                   /* symlink */
        NULL,                   /* mkdir */
        NULL,                   /* mkdir */
        NULL,                   /* rmdir */
        NULL,                   /* rmdir */
        NULL,                   /* mknod */
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* rename */
        NULL,                   /* readlink */
        NULL,                   /* readlink */
        NULL,                   /* follow_link */
        NULL,                   /* follow_link */
        NULL,                   /* readpage */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* writepage */
        NULL,                   /* bmap */
        NULL,                   /* bmap */
        NULL,                   /* truncate */
        NULL,                   /* truncate */
        NULL                    /* permission */
        NULL                    /* permission */
};
};
 
 
int do_pipe(int *fd)
int do_pipe(int *fd)
{
{
        struct inode * inode;
        struct inode * inode;
        struct file *f1, *f2;
        struct file *f1, *f2;
        int error;
        int error;
        int i,j;
        int i,j;
 
 
        error = -ENFILE;
        error = -ENFILE;
        f1 = get_empty_filp();
        f1 = get_empty_filp();
        if (!f1)
        if (!f1)
                goto no_files;
                goto no_files;
 
 
        f2 = get_empty_filp();
        f2 = get_empty_filp();
        if (!f2)
        if (!f2)
                goto close_f1;
                goto close_f1;
 
 
        inode = get_pipe_inode();
        inode = get_pipe_inode();
        if (!inode)
        if (!inode)
                goto close_f12;
                goto close_f12;
 
 
        error = get_unused_fd();
        error = get_unused_fd();
        if (error < 0)
        if (error < 0)
                goto close_f12_inode;
                goto close_f12_inode;
        i = error;
        i = error;
 
 
        error = get_unused_fd();
        error = get_unused_fd();
        if (error < 0)
        if (error < 0)
                goto close_f12_inode_i;
                goto close_f12_inode_i;
        j = error;
        j = error;
 
 
        f1->f_inode = f2->f_inode = inode;
        f1->f_inode = f2->f_inode = inode;
        /* read file */
        /* read file */
        f1->f_pos = f2->f_pos = 0;
        f1->f_pos = f2->f_pos = 0;
        f1->f_flags = O_RDONLY;
        f1->f_flags = O_RDONLY;
        f1->f_op = &read_pipe_fops;
        f1->f_op = &read_pipe_fops;
        f1->f_mode = 1;
        f1->f_mode = 1;
        /* write file */
        /* write file */
        f2->f_flags = O_WRONLY;
        f2->f_flags = O_WRONLY;
        f2->f_op = &write_pipe_fops;
        f2->f_op = &write_pipe_fops;
        f2->f_mode = 2;
        f2->f_mode = 2;
        current->files->fd[i] = f1;
        current->files->fd[i] = f1;
        current->files->fd[j] = f2;
        current->files->fd[j] = f2;
        fd[0] = i;
        fd[0] = i;
        fd[1] = j;
        fd[1] = j;
        return 0;
        return 0;
 
 
close_f12_inode_i:
close_f12_inode_i:
        put_unused_fd(i);
        put_unused_fd(i);
close_f12_inode:
close_f12_inode:
        inode->i_count--;
        inode->i_count--;
        iput(inode);
        iput(inode);
close_f12:
close_f12:
        f2->f_count--;
        f2->f_count--;
close_f1:
close_f1:
        f1->f_count--;
        f1->f_count--;
no_files:
no_files:
        return error;
        return error;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.