diff options
Diffstat (limited to 'usr/src/uts/common/syscall')
-rw-r--r-- | usr/src/uts/common/syscall/fcntl.c | 18 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/pipe.c | 74 |
2 files changed, 76 insertions, 16 deletions
diff --git a/usr/src/uts/common/syscall/fcntl.c b/usr/src/uts/common/syscall/fcntl.c index 4a6e58f6b0..43a50d6d58 100644 --- a/usr/src/uts/common/syscall/fcntl.c +++ b/usr/src/uts/common/syscall/fcntl.c @@ -22,6 +22,7 @@ /* ONC_PLUS EXTRACT START */ /* * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -32,6 +33,7 @@ * under license from the Regents of the University of California. */ + /* ONC_PLUS EXTRACT END */ #include <sys/param.h> @@ -151,6 +153,7 @@ fcntl(int fdes, int cmd, intptr_t arg) /* ONC_PLUS EXTRACT END */ case F_DUPFD: + case F_DUPFD_CLOEXEC: p = curproc; if ((uint_t)iarg >= p->p_fno_ctl) { if (iarg >= 0) @@ -178,9 +181,21 @@ fcntl(int fdes, int cmd, intptr_t arg) fp->f_count--; mutex_exit(&fp->f_tlock); error = EMFILE; + } else { + if (cmd == F_DUPFD_CLOEXEC) { + f_setfd(retval, FD_CLOEXEC); + } } goto done; + case F_DUP2FD_CLOEXEC: + if (fdes == iarg) { + error = EINVAL; + goto done; + } + + /* lint -fallthrough */ + case F_DUP2FD: p = curproc; if (fdes == iarg) { @@ -208,6 +223,9 @@ fcntl(int fdes, int cmd, intptr_t arg) mutex_exit(&fp->f_tlock); releasef(fdes); if ((error = closeandsetf(iarg, fp)) == 0) { + if (cmd == F_DUP2FD_CLOEXEC) { + f_setfd(iarg, FD_CLOEXEC); + } retval = iarg; } else { mutex_enter(&fp->f_tlock); diff --git a/usr/src/uts/common/syscall/pipe.c b/usr/src/uts/common/syscall/pipe.c index a626b2364a..1b9ea4f6db 100644 --- a/usr/src/uts/common/syscall/pipe.c +++ b/usr/src/uts/common/syscall/pipe.c @@ -19,6 +19,7 @@ * CDDL HEADER END */ /* + * Copyright 2013 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2011 Bayard G. Bell. All rights reserved. @@ -41,6 +42,7 @@ #include <sys/errno.h> #include <sys/debug.h> #include <sys/fs/fifonode.h> +#include <sys/fcntl.h> /* * This is the loadable module wrapper. @@ -48,11 +50,11 @@ #include <sys/modctl.h> #include <sys/syscall.h> -longlong_t pipe(); +int pipe(intptr_t fds, int); static struct sysent pipe_sysent = { - 0, - SE_32RVAL1 | SE_32RVAL2 | SE_NOUNLOAD | SE_ARGC, + 2, + SE_ARGC | SE_32RVAL1 | SE_NOUNLOAD, (int (*)())pipe }; @@ -102,16 +104,22 @@ _info(struct modinfo *modinfop) * each end of the pipe with a vnode, a file descriptor and * one of the streams. */ -longlong_t -pipe() +int +pipe(intptr_t arg, int flags) { vnode_t *vp1, *vp2; struct file *fp1, *fp2; int error = 0; + int flag1, flag2, iflags; int fd1, fd2; - rval_t r; /* + * Validate allowed flags. + */ + if (flags & ~(FCLOEXEC|FNONBLOCK) != 0) { + return (set_errno(EINVAL)); + } + /* * Allocate and initialize two vnodes. */ makepipe(&vp1, &vp2); @@ -124,7 +132,7 @@ pipe() if (error = falloc(vp1, FWRITE|FREAD, &fp1, &fd1)) { VN_RELE(vp1); VN_RELE(vp2); - return ((longlong_t)set_errno(error)); + return (set_errno(error)); } if (error = falloc(vp2, FWRITE|FREAD, &fp2, &fd2)) @@ -147,6 +155,36 @@ pipe() VTOF(vp1)->fn_ino = VTOF(vp2)->fn_ino = fifogetid(); /* + * Set the O_NONBLOCK flag if requested. + */ + if (flags & FNONBLOCK) { + flag1 = fp1->f_flag; + flag2 = fp2->f_flag; + iflags = flags & FNONBLOCK; + + if (error = VOP_SETFL(vp1, flag1, iflags, fp1->f_cred, NULL)) { + goto out_vop_close; + } + fp1->f_flag |= iflags; + + if (error = VOP_SETFL(vp2, flag2, iflags, fp2->f_cred, NULL)) { + goto out_vop_close; + } + fp2->f_flag |= iflags; + } + + /* + * Return the file descriptors to the user. They now + * point to two different vnodes which have different + * stream heads. + */ + if (copyout(&fd1, &((int *)arg)[0], sizeof (int)) || + copyout(&fd2, &((int *)arg)[1], sizeof (int))) { + error = EFAULT; + goto out_vop_close; + } + + /* * Now fill in the entries that falloc reserved */ mutex_exit(&fp1->f_tlock); @@ -155,20 +193,24 @@ pipe() setf(fd2, fp2); /* - * Return the file descriptors to the user. They now - * point to two different vnodes which have different - * stream heads. + * Optionally set the FCLOEXEC flag */ - r.r_val1 = fd1; - r.r_val2 = fd2; - return (r.r_vals); + if ((flags & FCLOEXEC) != 0) { + f_setfd(fd1, FD_CLOEXEC); + f_setfd(fd2, FD_CLOEXEC); + } + + return (0); +out_vop_close: + (void) VOP_CLOSE(vp1, FWRITE|FREAD, 1, (offset_t)0, fp1->f_cred, NULL); + (void) VOP_CLOSE(vp2, FWRITE|FREAD, 1, (offset_t)0, fp2->f_cred, NULL); out: - unfalloc(fp2); setf(fd2, NULL); + unfalloc(fp2); out2: - unfalloc(fp1); setf(fd1, NULL); + unfalloc(fp1); VN_RELE(vp1); VN_RELE(vp2); - return ((longlong_t)set_errno(error)); + return (set_errno(error)); } |