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