Merge commit '4ec4134be29a3b00791f6d70074168a6a3ff4fb3'
[unleashed.git] / kernel / syscall / pipe.c
blob9e19a5a3dd2f7a4b702104cfa8783ef4430b3282
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2013 OmniTI Computer Consulting, Inc. All rights reserved.
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
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 #include <sys/fcntl.h>
48 * This is the loadable module wrapper.
50 #include <sys/modctl.h>
51 #include <sys/syscall.h>
53 int pipe(intptr_t fds, int);
55 static struct sysent pipe_sysent = {
57 SE_ARGC | SE_32RVAL1 | SE_NOUNLOAD,
58 (int (*)())pipe
62 * Module linkage information for the kernel.
64 static struct modlsys modlsys = {
65 &mod_syscallops, "pipe(2) syscall", &pipe_sysent
68 #ifdef _SYSCALL32_IMPL
69 static struct modlsys modlsys32 = {
70 &mod_syscallops32, "32-bit pipe(2) syscall", &pipe_sysent
72 #endif
74 static struct modlinkage modlinkage = {
75 MODREV_1,
76 &modlsys,
77 #ifdef _SYSCALL32_IMPL
78 &modlsys32,
79 #endif
80 NULL
83 int
84 _init(void)
86 return (mod_install(&modlinkage));
89 int
90 _fini(void)
92 return (EBUSY);
95 int
96 _info(struct modinfo *modinfop)
98 return (mod_info(&modlinkage, modinfop));
102 * pipe(2) system call.
103 * Create a pipe by connecting two streams together. Associate
104 * each end of the pipe with a vnode, a file descriptor and
105 * one of the streams.
108 pipe(intptr_t arg, int flags)
110 vnode_t *vp1, *vp2;
111 struct file *fp1, *fp2;
112 int error = 0;
113 int flag1, flag2, iflags;
114 int fd1, fd2;
117 * Validate allowed flags.
119 if ((flags & ~(FCLOEXEC|FNONBLOCK)) != 0) {
120 return (set_errno(EINVAL));
123 * Allocate and initialize two vnodes.
125 makepipe(&vp1, &vp2);
128 * Allocate and initialize two file table entries and two
129 * file pointers. Each file pointer is open for read and
130 * write.
132 if (error = falloc(vp1, FWRITE|FREAD, &fp1, &fd1)) {
133 VN_RELE(vp1);
134 VN_RELE(vp2);
135 return (set_errno(error));
138 if (error = falloc(vp2, FWRITE|FREAD, &fp2, &fd2))
139 goto out2;
142 * Create two stream heads and attach to each vnode.
144 if (error = fifo_stropen(&vp1, FWRITE|FREAD, fp1->f_cred, 0, 0))
145 goto out;
147 if (error = fifo_stropen(&vp2, FWRITE|FREAD, fp2->f_cred, 0, 0)) {
148 (void) fop_close(vp1, FWRITE|FREAD, 1, (offset_t)0,
149 fp1->f_cred, NULL);
150 goto out;
153 strmate(vp1, vp2);
155 VTOF(vp1)->fn_ino = VTOF(vp2)->fn_ino = fifogetid();
158 * Set the O_NONBLOCK flag if requested.
160 if (flags & FNONBLOCK) {
161 flag1 = fp1->f_flag;
162 flag2 = fp2->f_flag;
163 iflags = flags & FNONBLOCK;
165 if (error = fop_setfl(vp1, flag1, iflags, fp1->f_cred, NULL)) {
166 goto out_vop_close;
168 fp1->f_flag |= iflags;
170 if (error = fop_setfl(vp2, flag2, iflags, fp2->f_cred, NULL)) {
171 goto out_vop_close;
173 fp2->f_flag |= iflags;
177 * Return the file descriptors to the user. They now
178 * point to two different vnodes which have different
179 * stream heads.
181 if (copyout(&fd1, &((int *)arg)[0], sizeof (int)) ||
182 copyout(&fd2, &((int *)arg)[1], sizeof (int))) {
183 error = EFAULT;
184 goto out_vop_close;
188 * Now fill in the entries that falloc reserved
190 mutex_exit(&fp1->f_tlock);
191 mutex_exit(&fp2->f_tlock);
192 setf(fd1, fp1);
193 setf(fd2, fp2);
196 * Optionally set the FCLOEXEC flag
198 if ((flags & FCLOEXEC) != 0) {
199 f_setfd(fd1, FD_CLOEXEC);
200 f_setfd(fd2, FD_CLOEXEC);
203 return (0);
204 out_vop_close:
205 (void) fop_close(vp1, FWRITE|FREAD, 1, (offset_t)0, fp1->f_cred, NULL);
206 (void) fop_close(vp2, FWRITE|FREAD, 1, (offset_t)0, fp2->f_cred, NULL);
207 out:
208 setf(fd2, NULL);
209 unfalloc(fp2);
210 out2:
211 setf(fd1, NULL);
212 unfalloc(fp1);
213 VN_RELE(vp1);
214 VN_RELE(vp2);
215 return (set_errno(error));