root/fs/pipe.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pipe_read
  2. pipe_write
  3. pipe_lseek
  4. pipe_readdir
  5. bad_pipe_rw
  6. pipe_ioctl
  7. pipe_select
  8. pipe_read_release
  9. pipe_write_release
  10. pipe_rdwr_release
  11. sys_pipe

   1 /*
   2  *  linux/fs/pipe.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #include <asm/segment.h>
   8 
   9 #include <linux/sched.h>
  10 #include <linux/kernel.h>
  11 #include <linux/errno.h>
  12 #include <linux/signal.h>
  13 #include <linux/fcntl.h>
  14 #include <linux/termios.h>
  15 
  16 static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  17 {
  18         int chars, size, read = 0;
  19 
  20         if (!(filp->f_flags & O_NONBLOCK))
  21                 while (!PIPE_SIZE(*inode)) {
  22                         wake_up(& PIPE_WRITE_WAIT(*inode));
  23                         if (!PIPE_WRITERS(*inode)) /* are there any writers? */
  24                                 return 0;
  25                         if (current->signal & ~current->blocked)
  26                                 return -ERESTARTSYS;
  27                         interruptible_sleep_on(& PIPE_READ_WAIT(*inode));
  28                 }
  29         while (count>0 && (size = PIPE_SIZE(*inode))) {
  30                 chars = PAGE_SIZE-PIPE_TAIL(*inode);
  31                 if (chars > count)
  32                         chars = count;
  33                 if (chars > size)
  34                         chars = size;
  35                 memcpy_tofs(buf, PIPE_BASE(*inode)+PIPE_TAIL(*inode), chars );
  36                 read += chars;
  37                 PIPE_TAIL(*inode) += chars;
  38                 PIPE_TAIL(*inode) &= (PAGE_SIZE-1);
  39                 count -= chars;
  40                 buf += chars;
  41         }
  42         wake_up(& PIPE_WRITE_WAIT(*inode));
  43         if (read)
  44                 return read;
  45         if (PIPE_WRITERS(*inode))
  46                 return -EAGAIN;
  47         return 0;
  48 }
  49         
  50 static int pipe_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52         int chars, size, written = 0;
  53 
  54         if (!PIPE_READERS(*inode)) { /* no readers */
  55                 send_sig(SIGPIPE,current,0);
  56                 return -EPIPE;
  57         }
  58 /* if count < PAGE_SIZE, we have to make it atomic */
  59         if (count < PAGE_SIZE)
  60                 size = PAGE_SIZE-count;
  61         else
  62                 size = PAGE_SIZE-1;
  63         while (count>0) {
  64                 while (PIPE_SIZE(*inode) >= size) {
  65                         if (!PIPE_READERS(*inode)) { /* no readers */
  66                                 send_sig(SIGPIPE,current,0);
  67                                 return written?written:-EPIPE;
  68                         }
  69                         if (current->signal & ~current->blocked)
  70                                 return written?written:-ERESTARTSYS;
  71                         if (filp->f_flags & O_NONBLOCK)
  72                                 return -EAGAIN;
  73                         else
  74                                 interruptible_sleep_on(&PIPE_WRITE_WAIT(*inode));
  75                 }
  76                 while (count>0 && (size = (PAGE_SIZE-1)-PIPE_SIZE(*inode))) {
  77                         chars = PAGE_SIZE-PIPE_HEAD(*inode);
  78                         if (chars > count)
  79                                 chars = count;
  80                         if (chars > size)
  81                                 chars = size;
  82                         memcpy_fromfs(PIPE_BASE(*inode)+PIPE_HEAD(*inode), buf, chars );
  83                         written += chars;
  84                         PIPE_HEAD(*inode) += chars;
  85                         PIPE_HEAD(*inode) &= (PAGE_SIZE-1);
  86                         count -= chars;
  87                         buf += chars;
  88                 }
  89                 wake_up(& PIPE_READ_WAIT(*inode));
  90                 size = PAGE_SIZE-1;
  91         }
  92         return written;
  93 }
  94 
  95 static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         return -ESPIPE;
  98 }
  99 
 100 static int pipe_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         return -ENOTDIR;
 103 }
 104 
 105 static int bad_pipe_rw(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 106 {
 107         return -EBADF;
 108 }
 109 
 110 static int pipe_ioctl(struct inode *pino, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 111         unsigned int cmd, unsigned long arg)
 112 {
 113         int error;
 114 
 115         switch (cmd) {
 116                 case FIONREAD:
 117                         error = verify_area(VERIFY_WRITE, (void *) arg,4);
 118                         if (!error)
 119                                 put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg);
 120                         return error;
 121                 default:
 122                         return -EINVAL;
 123         }
 124 }
 125 
 126 static int pipe_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 127 {
 128         switch (sel_type) {
 129                 case SEL_IN:
 130                         if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode))
 131                                 return 1;
 132                         select_wait(&PIPE_READ_WAIT(*inode), wait);
 133                         return 0;
 134                 case SEL_OUT:
 135                         if (!PIPE_FULL(*inode) || !PIPE_WRITERS(*inode))
 136                                 return 1;
 137                         select_wait(&PIPE_WRITE_WAIT(*inode), wait);
 138                         return 0;
 139                 case SEL_EX:
 140                         if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
 141                                 return 1;
 142                         select_wait(&inode->i_wait,wait);
 143                         return 0;
 144         }
 145         return 0;
 146 }
 147 
 148 /*
 149  * Ok, these three routines NOW keep track of readers/writers,
 150  * Linus previously did it with inode->i_count checking.
 151  */
 152 static void pipe_read_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 153 {
 154         PIPE_READERS(*inode)--;
 155         wake_up(&PIPE_WRITE_WAIT(*inode));
 156 }
 157 
 158 static void pipe_write_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160         PIPE_WRITERS(*inode)--;
 161         wake_up(&PIPE_READ_WAIT(*inode));
 162 }
 163 
 164 static void pipe_rdwr_release(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166         PIPE_READERS(*inode)--;
 167         PIPE_WRITERS(*inode)--;
 168         wake_up(&PIPE_READ_WAIT(*inode));
 169         wake_up(&PIPE_WRITE_WAIT(*inode));
 170 }
 171 
 172 /*
 173  * The three file_operations structs are not static because they
 174  * are also used in linux/fs/fifo.c to do operations on fifo's.
 175  */
 176 struct file_operations read_pipe_fops = {
 177         pipe_lseek,
 178         pipe_read,
 179         bad_pipe_rw,
 180         pipe_readdir,
 181         pipe_select,
 182         pipe_ioctl,
 183         NULL,           /* no mmap on pipes.. surprise */
 184         NULL,           /* no special open code */
 185         pipe_read_release,
 186         NULL
 187 };
 188 
 189 struct file_operations write_pipe_fops = {
 190         pipe_lseek,
 191         bad_pipe_rw,
 192         pipe_write,
 193         pipe_readdir,
 194         pipe_select,
 195         pipe_ioctl,
 196         NULL,           /* mmap */
 197         NULL,           /* no special open code */
 198         pipe_write_release,
 199         NULL
 200 };
 201 
 202 struct file_operations rdwr_pipe_fops = {
 203         pipe_lseek,
 204         pipe_read,
 205         pipe_write,
 206         pipe_readdir,
 207         pipe_select,
 208         pipe_ioctl,
 209         NULL,           /* mmap */
 210         NULL,           /* no special open code */
 211         pipe_rdwr_release,
 212         NULL
 213 };
 214 
 215 int sys_pipe(unsigned long * fildes)
     /* [previous][next][first][last][top][bottom][index][help] */
 216 {
 217         struct inode * inode;
 218         struct file * f[2];
 219         int fd[2];
 220         int i,j;
 221 
 222         j = verify_area(VERIFY_WRITE,fildes,8);
 223         if (j)
 224                 return j;
 225         for(j=0 ; j<2 ; j++)
 226                 if (!(f[j] = get_empty_filp()))
 227                         break;
 228         if (j==1)
 229                 f[0]->f_count--;
 230         if (j<2)
 231                 return -ENFILE;
 232         j=0;
 233         for(i=0;j<2 && i<NR_OPEN;i++)
 234                 if (!current->filp[i]) {
 235                         current->filp[ fd[j]=i ] = f[j];
 236                         j++;
 237                 }
 238         if (j==1)
 239                 current->filp[fd[0]]=NULL;
 240         if (j<2) {
 241                 f[0]->f_count--;
 242                 f[1]->f_count--;
 243                 return -EMFILE;
 244         }
 245         if (!(inode=get_pipe_inode())) {
 246                 current->filp[fd[0]] = NULL;
 247                 current->filp[fd[1]] = NULL;
 248                 f[0]->f_count--;
 249                 f[1]->f_count--;
 250                 return -ENFILE;
 251         }
 252         f[0]->f_inode = f[1]->f_inode = inode;
 253         f[0]->f_pos = f[1]->f_pos = 0;
 254         f[0]->f_flags = O_RDONLY;
 255         f[0]->f_op = &read_pipe_fops;
 256         f[0]->f_mode = 1;               /* read */
 257         f[1]->f_flags = O_WRONLY;
 258         f[1]->f_op = &write_pipe_fops;
 259         f[1]->f_mode = 2;               /* write */
 260         put_fs_long(fd[0],0+fildes);
 261         put_fs_long(fd[1],1+fildes);
 262         return 0;
 263 }

/* [previous][next][first][last][top][bottom][index][help] */