libc: Allow setting close-on-exec in fopen/freopen/fdopen.

This commit adds a new mode option 'e' that must follow any 'b', '+' and/or
'x' options. C11 is clear about the 'x' needing to follow 'b' and/or '+' and
that is what we implement; therefore, require a strict position for 'e' as
well.

For freopen() with a non-NULL path argument and fopen(), the close-on-exec
flag is set iff the 'e' mode option is specified. For freopen() with a NULL
path argument and fdopen(), the close-on-exec flag is turned on if the 'e'
mode option is specified and remains unchanged otherwise.

Although the same behaviour for fopen() can be obtained by open(O_CLOEXEC)
and fdopen(), this needlessly complicates the calling code.

Apart from the ordering requirement, the new option matches glibc.

PR:		kern/169320
This commit is contained in:
Jilles Tjoelker 2012-11-30 23:51:33 +00:00
parent 47dd71a877
commit 5ba651f004
4 changed files with 33 additions and 2 deletions

View File

@ -80,6 +80,12 @@ fdopen(fd, mode)
if ((fp = __sfp()) == NULL)
return (NULL);
if ((oflags & O_CLOEXEC) && _fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
fp->_flags = 0;
return (NULL);
}
fp->_flags = flags;
/*
* If opened for appending, but underlying descriptor does not have

View File

@ -97,6 +97,7 @@ __sflags(mode, optr)
/* 'x' means exclusive (fail if the file exists) */
if (*mode == 'x') {
mode++;
if (m == O_RDONLY) {
errno = EINVAL;
return (0);
@ -104,6 +105,10 @@ __sflags(mode, optr)
o |= O_EXCL;
}
/* set close-on-exec */
if (*mode == 'e')
o |= O_CLOEXEC;
*optr = m | o;
return (ret);
}

View File

@ -32,7 +32,7 @@
.\" @(#)fopen.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd October 17, 2011
.Dd November 30, 2012
.Dt FOPEN 3
.Os
.Sh NAME
@ -97,6 +97,14 @@ or
causes the
.Fn fopen
call to fail if the file already exists.
An optional
.Dq Li e
following the above
causes the
.Fn fopen
call to set the
.Dv FD_CLOEXEC
flag on the underlying file descriptor.
.Pp
The
.Fa mode
@ -144,6 +152,11 @@ of the stream must be compatible with the mode of the file descriptor.
The
.Dq Li x
mode option is ignored.
If the
.Dq Li e
mode option is present, the
.Dv FD_CLOEXEC
flag is set, otherwise it remains unchanged.
When the stream is closed via
.Xr fclose 3 ,
.Fa fildes
@ -277,3 +290,7 @@ The
function
conforms to
.St -p1003.1-88 .
The
.Dq Li e
mode option does not conform to any standard
but is also supported by glibc.

View File

@ -118,6 +118,8 @@ freopen(file, mode, fp)
(void) ftruncate(fp->_file, (off_t)0);
if (!(oflags & O_APPEND))
(void) _sseek(fp, (fpos_t)0, SEEK_SET);
if (oflags & O_CLOEXEC)
(void) _fcntl(fp->_file, F_SETFD, FD_CLOEXEC);
f = fp->_file;
isopen = 0;
wantfd = -1;
@ -194,7 +196,8 @@ freopen(file, mode, fp)
* assume stderr is always fd STDERR_FILENO, even if being freopen'd.
*/
if (wantfd >= 0) {
if (_dup2(f, wantfd) >= 0) {
if ((oflags & O_CLOEXEC ? _fcntl(f, F_DUP2FD_CLOEXEC, wantfd) :
_dup2(f, wantfd)) >= 0) {
(void)_close(f);
f = wantfd;
} else