home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / fs / pipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  9.1 KB  |  409 lines

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