/* Duplicate FD to FD2, closing the old FD2 and making FD2 be open the same file as FD is. Return FD2 or -1. */int__dup2 (int fd,int fd2){if (fd <0|| fd2 <0) {__set_errno (EBADF);return-1; }if (fd == fd2) /* No way to check that they are valid. */return fd2;__set_errno (ENOSYS);return-1;}
/* Create a named pipe (FIFO) named PATH with protections MODE. */intmkfifo (constchar*path,mode_t mode){dev_t dev =0;return__xmknod (_MKNOD_VER, path, mode | S_IFIFO,&dev);}/* Create a device file named PATH, with permission and special bits MODE and device number DEV (which can be constructed from major and minor device numbers with the `makedev' macro above). */int__xmknod (int vers,constchar*path,mode_t mode,dev_t*dev){unsignedlonglongint k_dev;if (vers != _MKNOD_VER)returnINLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); /* We must convert the value to dev_t type used by the kernel. */ k_dev = (*dev) & ((1ULL<<32) -1);if (k_dev !=*dev)returnINLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);returnINLINE_SYSCALL (mknod,3, path, mode, (unsignedint) k_dev);}
staticintfifo_open(struct inode *inode,struct file *filp){struct pipe_inode_info *pipe;bool is_pipe =inode->i_sb->s_magic == PIPEFS_MAGIC;int ret;filp->f_version =0;spin_lock(&inode->i_lock);if (inode->i_pipe) { pipe =inode->i_pipe;pipe->files++;spin_unlock(&inode->i_lock); } else {spin_unlock(&inode->i_lock); pipe =alloc_pipe_info();if (!pipe)return-ENOMEM;pipe->files =1;spin_lock(&inode->i_lock);if (unlikely(inode->i_pipe)) {inode->i_pipe->files++;spin_unlock(&inode->i_lock);free_pipe_info(pipe); pipe =inode->i_pipe; } else {inode->i_pipe = pipe;spin_unlock(&inode->i_lock); } }filp->private_data = pipe; /* OK, we have a pipe and it's pinned down */__pipe_lock(pipe); /* We can only do regular read/write on fifos */filp->f_mode &= (FMODE_READ | FMODE_WRITE);switch (filp->f_mode) {case FMODE_READ: /* * O_RDONLY * POSIX.1 says that O_NONBLOCK means return with the FIFO * opened, even when there is no process writing the FIFO. */pipe->r_counter++;if (pipe->readers++==0)wake_up_partner(pipe);if (!is_pipe &&!pipe->writers) {if ((filp->f_flags & O_NONBLOCK)) { /* suppress EPOLLHUP until we have * seen a writer */filp->f_version =pipe->w_counter; } else {if (wait_for_partner(pipe,&pipe->w_counter))goto err_rd; } }break;case FMODE_WRITE: /* * O_WRONLY * POSIX.1 says that O_NONBLOCK means return -1 with * errno=ENXIO when there is no process reading the FIFO. */ ret =-ENXIO;if (!is_pipe && (filp->f_flags & O_NONBLOCK) &&!pipe->readers)goto err;pipe->w_counter++;if (!pipe->writers++)wake_up_partner(pipe);if (!is_pipe &&!pipe->readers) {if (wait_for_partner(pipe,&pipe->r_counter))goto err_wr; }break;case FMODE_READ | FMODE_WRITE: /* * O_RDWR * POSIX.1 leaves this case "undefined" when O_NONBLOCK is set. * This implementation will NEVER block on a O_RDWR open, since * the process can at least talk to itself. */pipe->readers++;pipe->writers++;pipe->r_counter++;pipe->w_counter++;if (pipe->readers ==1|| pipe->writers ==1)wake_up_partner(pipe);break;default: ret =-EINVAL;goto err; } /* Ok! */__pipe_unlock(pipe);return0;......}