xref: /illumos-gate/usr/src/uts/common/syscall/pipe.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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	"%Z%%M%	%I%	%E% 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