Home | History | Annotate | Download | only in syscall
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     27 /*	  All Rights Reserved  	*/
     28 
     29 
     30 #pragma ident	"@(#)pipe.c	1.29	07/10/25 SMI"	/* from SVr4.0 1.11 */
     31 
     32 #include <sys/types.h>
     33 #include <sys/sysmacros.h>
     34 #include <sys/param.h>
     35 #include <sys/systm.h>
     36 #include <sys/cred.h>
     37 #include <sys/user.h>
     38 #include <sys/vnode.h>
     39 #include <sys/file.h>
     40 #include <sys/stream.h>
     41 #include <sys/strsubr.h>
     42 #include <sys/errno.h>
     43 #include <sys/debug.h>
     44 #include <sys/fs/fifonode.h>
     45 
     46 /*
     47  * This is the loadable module wrapper.
     48  */
     49 #include <sys/modctl.h>
     50 #include <sys/syscall.h>
     51 
     52 char _depends_on[] = "fs/fifofs";
     53 
     54 longlong_t pipe();
     55 
     56 static struct sysent pipe_sysent = {
     57 	0,
     58 	SE_32RVAL1 | SE_32RVAL2 | SE_NOUNLOAD | SE_ARGC,
     59 	(int (*)())pipe
     60 };
     61 
     62 /*
     63  * Module linkage information for the kernel.
     64  */
     65 static struct modlsys modlsys = {
     66 	&mod_syscallops, "pipe(2) syscall", &pipe_sysent
     67 };
     68 
     69 #ifdef _SYSCALL32_IMPL
     70 static struct modlsys modlsys32 = {
     71 	&mod_syscallops32, "32-bit pipe(2) syscall", &pipe_sysent
     72 };
     73 #endif
     74 
     75 static struct modlinkage modlinkage = {
     76 	MODREV_1,
     77 	&modlsys,
     78 #ifdef _SYSCALL32_IMPL
     79 	&modlsys32,
     80 #endif
     81 	NULL
     82 };
     83 
     84 int
     85 _init(void)
     86 {
     87 	return (mod_install(&modlinkage));
     88 }
     89 
     90 int
     91 _fini(void)
     92 {
     93 	return (EBUSY);
     94 }
     95 
     96 int
     97 _info(struct modinfo *modinfop)
     98 {
     99 	return (mod_info(&modlinkage, modinfop));
    100 }
    101 
    102 /*
    103  * pipe(2) system call.
    104  * Create a pipe by connecting two streams together. Associate
    105  * each end of the pipe with a vnode, a file descriptor and
    106  * one of the streams.
    107  */
    108 longlong_t
    109 pipe()
    110 {
    111 	vnode_t *vp1, *vp2;
    112 	struct file *fp1, *fp2;
    113 	int error = 0;
    114 	int fd1, fd2;
    115 	rval_t	r;
    116 
    117 	/*
    118 	 * Allocate and initialize two vnodes.
    119 	 */
    120 	makepipe(&vp1, &vp2);
    121 
    122 	/*
    123 	 * Allocate and initialize two file table entries and two
    124 	 * file pointers. Each file pointer is open for read and
    125 	 * write.
    126 	 */
    127 	if (error = falloc(vp1, FWRITE|FREAD, &fp1, &fd1)) {
    128 		VN_RELE(vp1);
    129 		VN_RELE(vp2);
    130 		return ((longlong_t)set_errno(error));
    131 	}
    132 
    133 	if (error = falloc(vp2, FWRITE|FREAD, &fp2, &fd2))
    134 		goto out2;
    135 
    136 	/*
    137 	 * Create two stream heads and attach to each vnode.
    138 	 */
    139 	if (error = fifo_stropen(&vp1, FWRITE|FREAD, fp1->f_cred, 0, 0))
    140 		goto out;
    141 
    142 	if (error = fifo_stropen(&vp2, FWRITE|FREAD, fp2->f_cred, 0, 0)) {
    143 		(void) VOP_CLOSE(vp1, FWRITE|FREAD, 1, (offset_t)0,
    144 		    fp1->f_cred, NULL);
    145 		goto out;
    146 	}
    147 
    148 	strmate(vp1, vp2);
    149 
    150 	VTOF(vp1)->fn_ino = VTOF(vp2)->fn_ino = fifogetid();
    151 
    152 	/*
    153 	 * Now fill in the entries that falloc reserved
    154 	 */
    155 	mutex_exit(&fp1->f_tlock);
    156 	mutex_exit(&fp2->f_tlock);
    157 	setf(fd1, fp1);
    158 	setf(fd2, fp2);
    159 
    160 	/*
    161 	 * Return the file descriptors to the user. They now
    162 	 * point to two different vnodes which have different
    163 	 * stream heads.
    164 	 */
    165 	r.r_val1 = fd1;
    166 	r.r_val2 = fd2;
    167 	return (r.r_vals);
    168 out:
    169 	unfalloc(fp2);
    170 	setf(fd2, NULL);
    171 out2:
    172 	unfalloc(fp1);
    173 	setf(fd1, NULL);
    174 	VN_RELE(vp1);
    175 	VN_RELE(vp2);
    176 	return ((longlong_t)set_errno(error));
    177 }
    178