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