xref: /titanic_52/usr/src/uts/common/syscall/pipe.c (revision 2c2d21e98a95cba5687ec6574c974a5c6c4a6adb)
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  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 #include <sys/types.h>
32 #include <sys/sysmacros.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/cred.h>
36 #include <sys/user.h>
37 #include <sys/vnode.h>
38 #include <sys/file.h>
39 #include <sys/stream.h>
40 #include <sys/strsubr.h>
41 #include <sys/errno.h>
42 #include <sys/debug.h>
43 #include <sys/fs/fifonode.h>
44 
45 /*
46  * This is the loadable module wrapper.
47  */
48 #include <sys/modctl.h>
49 #include <sys/syscall.h>
50 
51 longlong_t pipe();
52 
53 static struct sysent pipe_sysent = {
54 	0,
55 	SE_32RVAL1 | SE_32RVAL2 | SE_NOUNLOAD | SE_ARGC,
56 	(int (*)())pipe
57 };
58 
59 /*
60  * Module linkage information for the kernel.
61  */
62 static struct modlsys modlsys = {
63 	&mod_syscallops, "pipe(2) syscall", &pipe_sysent
64 };
65 
66 #ifdef _SYSCALL32_IMPL
67 static struct modlsys modlsys32 = {
68 	&mod_syscallops32, "32-bit pipe(2) syscall", &pipe_sysent
69 };
70 #endif
71 
72 static struct modlinkage modlinkage = {
73 	MODREV_1,
74 	&modlsys,
75 #ifdef _SYSCALL32_IMPL
76 	&modlsys32,
77 #endif
78 	NULL
79 };
80 
81 int
82 _init(void)
83 {
84 	return (mod_install(&modlinkage));
85 }
86 
87 int
88 _fini(void)
89 {
90 	return (EBUSY);
91 }
92 
93 int
94 _info(struct modinfo *modinfop)
95 {
96 	return (mod_info(&modlinkage, modinfop));
97 }
98 
99 /*
100  * pipe(2) system call.
101  * Create a pipe by connecting two streams together. Associate
102  * each end of the pipe with a vnode, a file descriptor and
103  * one of the streams.
104  */
105 longlong_t
106 pipe()
107 {
108 	vnode_t *vp1, *vp2;
109 	struct file *fp1, *fp2;
110 	int error = 0;
111 	int fd1, fd2;
112 	rval_t	r;
113 
114 	/*
115 	 * Allocate and initialize two vnodes.
116 	 */
117 	makepipe(&vp1, &vp2);
118 
119 	/*
120 	 * Allocate and initialize two file table entries and two
121 	 * file pointers. Each file pointer is open for read and
122 	 * write.
123 	 */
124 	if (error = falloc(vp1, FWRITE|FREAD, &fp1, &fd1)) {
125 		VN_RELE(vp1);
126 		VN_RELE(vp2);
127 		return ((longlong_t)set_errno(error));
128 	}
129 
130 	if (error = falloc(vp2, FWRITE|FREAD, &fp2, &fd2))
131 		goto out2;
132 
133 	/*
134 	 * Create two stream heads and attach to each vnode.
135 	 */
136 	if (error = fifo_stropen(&vp1, FWRITE|FREAD, fp1->f_cred, 0, 0))
137 		goto out;
138 
139 	if (error = fifo_stropen(&vp2, FWRITE|FREAD, fp2->f_cred, 0, 0)) {
140 		(void) VOP_CLOSE(vp1, FWRITE|FREAD, 1, (offset_t)0,
141 		    fp1->f_cred, NULL);
142 		goto out;
143 	}
144 
145 	strmate(vp1, vp2);
146 
147 	VTOF(vp1)->fn_ino = VTOF(vp2)->fn_ino = fifogetid();
148 
149 	/*
150 	 * Now fill in the entries that falloc reserved
151 	 */
152 	mutex_exit(&fp1->f_tlock);
153 	mutex_exit(&fp2->f_tlock);
154 	setf(fd1, fp1);
155 	setf(fd2, fp2);
156 
157 	/*
158 	 * Return the file descriptors to the user. They now
159 	 * point to two different vnodes which have different
160 	 * stream heads.
161 	 */
162 	r.r_val1 = fd1;
163 	r.r_val2 = fd2;
164 	return (r.r_vals);
165 out:
166 	unfalloc(fp2);
167 	setf(fd2, NULL);
168 out2:
169 	unfalloc(fp1);
170 	setf(fd1, NULL);
171 	VN_RELE(vp1);
172 	VN_RELE(vp2);
173 	return ((longlong_t)set_errno(error));
174 }
175