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:
parent
47dd71a877
commit
5ba651f004
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user