home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / pipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-27  |  9.7 KB  |  428 lines

  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. #include <linux/mm.h>
  16.  
  17.  
  18. /* We don't use the head/tail construction any more. Now we use the start/len*/
  19. /* construction providing full use of PIPE_BUF (multiple of PAGE_SIZE) */
  20. /* Florian Coosmann (FGC)                                ^ current = 1       */
  21. /* Additionally, we now use locking technique. This prevents race condition  */
  22. /* in case of paging and multiple read/write on the same pipe. (FGC)         */
  23.  
  24.  
  25. static int pipe_read(struct inode * inode, struct file * filp, char * buf, int count)
  26. {
  27.     int chars = 0, size = 0, read = 0;
  28.         char *pipebuf;
  29.  
  30.     if (filp->f_flags & O_NONBLOCK) {
  31.         if (PIPE_LOCK(*inode))
  32.             return -EAGAIN;
  33.         if (PIPE_EMPTY(*inode))
  34.             if (PIPE_WRITERS(*inode))
  35.                 return -EAGAIN;
  36.             else
  37.                 return 0;
  38.     } else while (PIPE_EMPTY(*inode) || PIPE_LOCK(*inode)) {
  39.         if (PIPE_EMPTY(*inode)) {
  40.             if (!PIPE_WRITERS(*inode))
  41.                 return 0;
  42.         }
  43.         if (current->signal & ~current->blocked)
  44.             return -ERESTARTSYS;
  45.         interruptible_sleep_on(&PIPE_WAIT(*inode));
  46.     }
  47.     PIPE_LOCK(*inode)++;
  48.     while (count>0 && (size = PIPE_SIZE(*inode))) {
  49.         chars = PIPE_MAX_RCHUNK(*inode);
  50.         if (chars > count)
  51.             chars = count;
  52.         if (chars > size)
  53.             chars = size;
  54.         read += chars;
  55.                 pipebuf = PIPE_BASE(*inode)+PIPE_START(*inode);
  56.         PIPE_START(*inode) += chars;
  57.         PIPE_START(*inode) &= (PIPE_BUF-1);
  58.         PIPE_LEN(*inode) -= chars;
  59.         count -= chars;
  60.         memcpy_tofs(buf, pipebuf, chars );
  61.         buf += chars;
  62.     }
  63.     PIPE_LOCK(*inode)--;
  64.     wake_up_interruptible(&PIPE_WAIT(*inode));
  65.     if (read)
  66.         return read;
  67.     if (PIPE_WRITERS(*inode))
  68.         return -EAGAIN;
  69.     return 0;
  70. }
  71.     
  72. static int pipe_write(struct inode * inode, struct file * filp, char * buf, int count)
  73. {
  74.     int chars = 0, free = 0, written = 0;
  75.     char *pipebuf;
  76.  
  77.     if (!PIPE_READERS(*inode)) { /* no readers */
  78.         send_sig(SIGPIPE,current,0);
  79.         return -EPIPE;
  80.     }
  81. /* if count <= PIPE_BUF, we have to make it atomic */
  82.     if (count <= PIPE_BUF)
  83.         free = count;
  84.     else
  85.         free = 1; /* can't do it atomically, wait for any free space */
  86.     while (count>0) {
  87.         while ((PIPE_FREE(*inode) < free) || PIPE_LOCK(*inode)) {
  88.             if (!PIPE_READERS(*inode)) { /* no readers */
  89.                 send_sig(SIGPIPE,current,0);
  90.                 return written? :-EPIPE;
  91.             }
  92.             if (current->signal & ~current->blocked)
  93.                 return written? :-ERESTARTSYS;
  94.             if (filp->f_flags & O_NONBLOCK)
  95.                 return written? :-EAGAIN;
  96.             interruptible_sleep_on(&PIPE_WAIT(*inode));
  97.         }
  98.         PIPE_LOCK(*inode)++;
  99.         while (count>0 && (free = PIPE_FREE(*inode))) {
  100.             chars = PIPE_MAX_WCHUNK(*inode);
  101.             if (chars > count)
  102.                 chars = count;
  103.             if (chars > free)
  104.                 chars = free;
  105.                         pipebuf = PIPE_BASE(*inode)+PIPE_END(*inode);
  106.             written += chars;
  107.             PIPE_LEN(*inode) += chars;
  108.             count -= chars;
  109.             memcpy_fromfs(pipebuf, buf, chars );
  110.             buf += chars;
  111.         }
  112.         PIPE_LOCK(*inode)--;
  113.         wake_up_interruptible(&PIPE_WAIT(*inode));
  114.         free = 1;
  115.     }
  116.     return written;
  117. }
  118.  
  119. static int pipe_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
  120. {
  121.     return -ESPIPE;
  122. }
  123.  
  124. static int pipe_readdir(struct inode * inode, struct file * file, struct dirent * de, int count)
  125. {
  126.     return -ENOTDIR;
  127. }
  128.  
  129. static int bad_pipe_rw(struct inode * inode, struct file * filp, char * buf, int count)
  130. {
  131.     return -EBADF;
  132. }
  133.  
  134. static int pipe_ioctl(struct inode *pino, struct file * filp,
  135.     unsigned int cmd, unsigned long arg)
  136. {
  137.     int error;
  138.  
  139.     switch (cmd) {
  140.         case FIONREAD:
  141.             error = verify_area(VERIFY_WRITE, (void *) arg,4);
  142.             if (!error)
  143.                 put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg);
  144.             return error;
  145.         default:
  146.             return -EINVAL;
  147.     }
  148. }
  149.  
  150. static int pipe_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
  151. {
  152.     switch (sel_type) {
  153.         case SEL_IN:
  154.             if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode))
  155.                 return 1;
  156.             select_wait(&PIPE_WAIT(*inode), wait);
  157.             return 0;
  158.         case SEL_OUT:
  159.             if (!PIPE_FULL(*inode) || !PIPE_READERS(*inode))
  160.                 return 1;
  161.             select_wait(&PIPE_WAIT(*inode), wait);
  162.             return 0;
  163.         case SEL_EX:
  164.             if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
  165.                 return 1;
  166.             select_wait(&inode->i_wait,wait);
  167.             return 0;
  168.     }
  169.     return 0;
  170. }
  171.  
  172. /*
  173.  * Arggh. Why does SunOS have to have different select() behaviour
  174.  * for pipes and fifos? Hate-Hate-Hate. See difference in SEL_IN..
  175.  */
  176. static int fifo_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
  177. {
  178.     switch (sel_type) {
  179.         case SEL_IN:
  180.             if (!PIPE_EMPTY(*inode))
  181.                 return 1;
  182.             select_wait(&PIPE_WAIT(*inode), wait);
  183.             return 0;
  184.         case SEL_OUT:
  185.             if (!PIPE_FULL(*inode) || !PIPE_READERS(*inode))
  186.                 return 1;
  187.             select_wait(&PIPE_WAIT(*inode), wait);
  188.             return 0;
  189.         case SEL_EX:
  190.             if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
  191.                 return 1;
  192.             select_wait(&inode->i_wait,wait);
  193.             return 0;
  194.     }
  195.     return 0;
  196. }
  197.  
  198. /*
  199.  * The 'connect_xxx()' functions are needed for named pipes when
  200.  * the open() code hasn't guaranteed a connection (O_NONBLOCK),
  201.  * and we need to act differently until we do get a writer..
  202.  */
  203. static int connect_read(struct inode * inode, struct file * filp, char * buf, int count)
  204. {
  205.     while (!PIPE_SIZE(*inode)) {
  206.         if (PIPE_WRITERS(*inode))
  207.             break;
  208.         if (filp->f_flags & O_NONBLOCK)
  209.             return -EAGAIN;
  210.         wake_up_interruptible(& PIPE_WAIT(*inode));
  211.         if (current->signal & ~current->blocked)
  212.             return -ERESTARTSYS;
  213.         interruptible_sleep_on(& PIPE_WAIT(*inode));
  214.     }
  215.     filp->f_op = &read_fifo_fops;
  216.     return pipe_read(inode,filp,buf,count);
  217. }
  218.  
  219. static int connect_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait)
  220. {
  221.     switch (sel_type) {
  222.         case SEL_IN:
  223.             if (!PIPE_EMPTY(*inode)) {
  224.                 filp->f_op = &read_fifo_fops;
  225.                 return 1;
  226.             }
  227.             select_wait(&PIPE_WAIT(*inode), wait);
  228.             return 0;
  229.         case SEL_OUT:
  230.             if (!PIPE_FULL(*inode))
  231.                 return 1;
  232.             select_wait(&PIPE_WAIT(*inode), wait);
  233.             return 0;
  234.         case SEL_EX:
  235.             if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode))
  236.                 return 1;
  237.             select_wait(&inode->i_wait,wait);
  238.             return 0;
  239.     }
  240.     return 0;
  241. }
  242.  
  243. /*
  244.  * Ok, these three routines NOW keep track of readers/writers,
  245.  * Linus previously did it with inode->i_count checking.
  246.  */
  247. static void pipe_read_release(struct inode * inode, struct file * filp)
  248. {
  249.     PIPE_READERS(*inode)--;
  250.     wake_up_interruptible(&PIPE_WAIT(*inode));
  251. }
  252.  
  253. static void pipe_write_release(struct inode * inode, struct file * filp)
  254. {
  255.     PIPE_WRITERS(*inode)--;
  256.     wake_up_interruptible(&PIPE_WAIT(*inode));
  257. }
  258.  
  259. static void pipe_rdwr_release(struct inode * inode, struct file * filp)
  260. {
  261.     PIPE_READERS(*inode)--;
  262.     PIPE_WRITERS(*inode)--;
  263.     wake_up_interruptible(&PIPE_WAIT(*inode));
  264. }
  265.  
  266. /*
  267.  * The file_operations structs are not static because they
  268.  * are also used in linux/fs/fifo.c to do operations on fifo's.
  269.  */
  270. struct file_operations connecting_fifo_fops = {
  271.     pipe_lseek,
  272.     connect_read,
  273.     bad_pipe_rw,
  274.     pipe_readdir,
  275.     connect_select,
  276.     pipe_ioctl,
  277.     NULL,        /* no mmap on pipes.. surprise */
  278.     NULL,        /* no special open code */
  279.     pipe_read_release,
  280.     NULL
  281. };
  282.  
  283. struct file_operations read_fifo_fops = {
  284.     pipe_lseek,
  285.     pipe_read,
  286.     bad_pipe_rw,
  287.     pipe_readdir,
  288.     fifo_select,
  289.     pipe_ioctl,
  290.     NULL,        /* no mmap on pipes.. surprise */
  291.     NULL,        /* no special open code */
  292.     pipe_read_release,
  293.     NULL
  294. };
  295.  
  296. struct file_operations write_fifo_fops = {
  297.     pipe_lseek,
  298.     bad_pipe_rw,
  299.     pipe_write,
  300.     pipe_readdir,
  301.     fifo_select,
  302.     pipe_ioctl,
  303.     NULL,        /* mmap */
  304.     NULL,        /* no special open code */
  305.     pipe_write_release,
  306.     NULL
  307. };
  308.  
  309. struct file_operations rdwr_fifo_fops = {
  310.     pipe_lseek,
  311.     pipe_read,
  312.     pipe_write,
  313.     pipe_readdir,
  314.     fifo_select,
  315.     pipe_ioctl,
  316.     NULL,        /* mmap */
  317.     NULL,        /* no special open code */
  318.     pipe_rdwr_release,
  319.     NULL
  320. };
  321.  
  322. struct file_operations read_pipe_fops = {
  323.     pipe_lseek,
  324.     pipe_read,
  325.     bad_pipe_rw,
  326.     pipe_readdir,
  327.     pipe_select,
  328.     pipe_ioctl,
  329.     NULL,        /* no mmap on pipes.. surprise */
  330.     NULL,        /* no special open code */
  331.     pipe_read_release,
  332.     NULL
  333. };
  334.  
  335. struct file_operations write_pipe_fops = {
  336.     pipe_lseek,
  337.     bad_pipe_rw,
  338.     pipe_write,
  339.     pipe_readdir,
  340.     pipe_select,
  341.     pipe_ioctl,
  342.     NULL,        /* mmap */
  343.     NULL,        /* no special open code */
  344.     pipe_write_release,
  345.     NULL
  346. };
  347.  
  348. struct file_operations rdwr_pipe_fops = {
  349.     pipe_lseek,
  350.     pipe_read,
  351.     pipe_write,
  352.     pipe_readdir,
  353.     pipe_select,
  354.     pipe_ioctl,
  355.     NULL,        /* mmap */
  356.     NULL,        /* no special open code */
  357.     pipe_rdwr_release,
  358.     NULL
  359. };
  360.  
  361. struct inode_operations pipe_inode_operations = {
  362.     &rdwr_pipe_fops,
  363.     NULL,            /* create */
  364.     NULL,            /* lookup */
  365.     NULL,            /* link */
  366.     NULL,            /* unlink */
  367.     NULL,            /* symlink */
  368.     NULL,            /* mkdir */
  369.     NULL,            /* rmdir */
  370.     NULL,            /* mknod */
  371.     NULL,            /* rename */
  372.     NULL,            /* readlink */
  373.     NULL,            /* follow_link */
  374.     NULL,            /* bmap */
  375.     NULL,            /* truncate */
  376.     NULL            /* permission */
  377. };
  378.  
  379. asmlinkage int sys_pipe(unsigned long * fildes)
  380. {
  381.     struct inode * inode;
  382.     struct file * f[2];
  383.     int fd[2];
  384.     int i,j;
  385.  
  386.     j = verify_area(VERIFY_WRITE,fildes,8);
  387.     if (j)
  388.         return j;
  389.     for(j=0 ; j<2 ; j++)
  390.         if (!(f[j] = get_empty_filp()))
  391.             break;
  392.     if (j==1)
  393.         f[0]->f_count--;
  394.     if (j<2)
  395.         return -ENFILE;
  396.     j=0;
  397.     for(i=0;j<2 && i<NR_OPEN && i<current->rlim[RLIMIT_NOFILE].rlim_cur;i++)
  398.         if (!current->files->fd[i]) {
  399.             current->files->fd[ fd[j]=i ] = f[j];
  400.             j++;
  401.         }
  402.     if (j==1)
  403.         current->files->fd[fd[0]]=NULL;
  404.     if (j<2) {
  405.         f[0]->f_count--;
  406.         f[1]->f_count--;
  407.         return -EMFILE;
  408.     }
  409.     if (!(inode=get_pipe_inode())) {
  410.         current->files->fd[fd[0]] = NULL;
  411.         current->files->fd[fd[1]] = NULL;
  412.         f[0]->f_count--;
  413.         f[1]->f_count--;
  414.         return -ENFILE;
  415.     }
  416.     f[0]->f_inode = f[1]->f_inode = inode;
  417.     f[0]->f_pos = f[1]->f_pos = 0;
  418.     f[0]->f_flags = O_RDONLY;
  419.     f[0]->f_op = &read_pipe_fops;
  420.     f[0]->f_mode = 1;        /* read */
  421.     f[1]->f_flags = O_WRONLY;
  422.     f[1]->f_op = &write_pipe_fops;
  423.     f[1]->f_mode = 2;        /* write */
  424.     put_fs_long(fd[0],0+fildes);
  425.     put_fs_long(fd[1],1+fildes);
  426.     return 0;
  427. }
  428.