From dc570d5e563382f8f29248e6e5ecf8b8cb3887ed Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Wed, 1 May 2013 22:42:42 +0000 Subject: [PATCH] Add pipe2() system call. The pipe2() function is similar to pipe() but allows setting FD_CLOEXEC and O_NONBLOCK (on both sides) as part of the function. If p points to two writable ints, pipe2(p, 0) is equivalent to pipe(p). If the pointer is not valid, behaviour differs: pipe2() writes into the array from the kernel like socketpair() does, while pipe() writes into the array from an architecture-specific assembler wrapper. Reviewed by: kan, kib --- include/unistd.h | 1 + lib/libc/sys/Makefile.inc | 1 + lib/libc/sys/Symbol.map | 1 + lib/libc/sys/pipe.2 | 46 ++++++++++++++++++++++++++-- sys/compat/freebsd32/syscalls.master | 1 + sys/kern/capabilities.conf | 1 + sys/kern/sys_pipe.c | 18 +++++++++++ sys/kern/syscalls.master | 1 + 8 files changed, 68 insertions(+), 2 deletions(-) diff --git a/include/unistd.h b/include/unistd.h index dabf1780c455..9df07774c911 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -533,6 +533,7 @@ char *mktemp(char *); #endif int nfssvc(int, void *); int nlm_syscall(int, int, int, char **); +int pipe2(int *, int); int profil(char *, size_t, vm_offset_t, int); int rcmd(char **, int, const char *, const char *, const char *, int *); int rcmd_af(char **, int, const char *, diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index 105f46907528..8e918bf63cd2 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -352,6 +352,7 @@ MLINKS+=pathconf.2 lpathconf.2 MLINKS+=pdfork.2 pdgetpid.2\ pdfork.2 pdkill.2 \ pdfork.2 pdwait4.2 +MLINKS+=pipe.2 pipe2.2 MLINKS+=read.2 pread.2 \ read.2 preadv.2 \ read.2 readv.2 diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index 149fa417b50a..24f462125513 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -393,6 +393,7 @@ FBSD_1.3 { ffclock_getcounter; ffclock_getestimate; ffclock_setestimate; + pipe2; posix_fadvise; wait6; }; diff --git a/lib/libc/sys/pipe.2 b/lib/libc/sys/pipe.2 index 92d137fda091..bb3db51f5ffe 100644 --- a/lib/libc/sys/pipe.2 +++ b/lib/libc/sys/pipe.2 @@ -28,7 +28,7 @@ .\" @(#)pipe.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd January 30, 2006 +.Dd March 31, 2013 .Dt PIPE 2 .Os .Sh NAME @@ -40,6 +40,8 @@ .In unistd.h .Ft int .Fn pipe "int fildes[2]" +.Ft int +.Fn pipe2 "int fildes[2]" "int flags" .Sh DESCRIPTION The .Fn pipe @@ -50,6 +52,29 @@ which is an object allowing bidirectional data flow, and allocates a pair of file descriptors. .Pp +The +.Fn pipe2 +system call allows control over the attributes of the file descriptors +via the +.Fa flags +argument. +Values for +.Fa flags +are constructed by a bitwise-inclusive OR of flags from the following +list, defined in +.In fcntl.h : +.Bl -tag -width ".Dv O_NONBLOCK" +.It Dv O_CLOEXEC +Set the close-on-exec flag for the new file descriptors. +.It Dv O_NONBLOCK +Set the non-blocking flag for the ends of the pipe. +.El +.Pp +If the +.Fa flags +argument is 0, the behavior is identical to a call to +.Fn pipe . +.Pp By convention, the first descriptor is normally used as the .Em read end of the pipe, @@ -88,7 +113,9 @@ pipe in one direction. .Sh ERRORS The .Fn pipe -system call will fail if: +and +.Fn pipe2 +system calls will fail if: .Bl -tag -width Er .It Bq Er EMFILE Too many descriptors are active. @@ -97,6 +124,16 @@ The system file table is full. .It Bq Er ENOMEM Not enough kernel memory to establish a pipe. .El +.Pp +The +.Fn pipe2 +system call will also fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Fa flags +argument is invalid. +.El .Sh SEE ALSO .Xr sh 1 , .Xr fork 2 , @@ -111,3 +148,8 @@ function appeared in .Pp Bidirectional pipes were first used on .At V.4 . +.Pp +The +.Fn pipe2 +function appeared in +.Fx 10.0 . diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 2cbdf31e6721..be245be55346 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -1026,3 +1026,4 @@ struct sockaddr * __restrict name, \ __socklen_t * __restrict anamelen, \ int flags); } +542 AUE_PIPE NOPROTO { int pipe2(int *fildes, int flags); } diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf index 0b64503c466a..d2fa51c4ef84 100644 --- a/sys/kern/capabilities.conf +++ b/sys/kern/capabilities.conf @@ -490,6 +490,7 @@ pdkill ## Allow pipe(2). ## pipe +pipe2 ## ## Allow poll(2), which will be scoped by capability rights. diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 90c3022c1fd8..493fee5e2756 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -477,6 +477,24 @@ sys_pipe(struct thread *td, struct pipe_args *uap) return (0); } +int +sys_pipe2(struct thread *td, struct pipe2_args *uap) +{ + int error, fildes[2]; + + if (uap->flags & ~(O_CLOEXEC | O_NONBLOCK)) + return (EINVAL); + error = kern_pipe2(td, fildes, uap->flags); + if (error) + return (error); + error = copyout(fildes, uap->fildes, 2 * sizeof(int)); + if (error) { + (void)kern_close(td, fildes[0]); + (void)kern_close(td, fildes[1]); + } + return (error); +} + /* * Allocate kva for pipe circular buffer, the space is pageable * This routine will 'realloc' the size of a pipe safely, if it fails diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 922db305f049..86689434e196 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -976,5 +976,6 @@ struct sockaddr * __restrict name, \ __socklen_t * __restrict anamelen, \ int flags); } +542 AUE_PIPE STD { int pipe2(int *fildes, int flags); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master