Add fdclose(3) function.

This function is equivalent to fclose(3) function except that it
does not close the underlying file descriptor.
fdclose(3) is step forward to make FILE structure private.

Reviewed by:	wblock, jilles, jhb, pjd
Approved by:	pjd (mentor)
Differential Revision:	https://reviews.freebsd.org/D2697
This commit is contained in:
Mariusz Zaborski 2015-07-04 16:42:14 +00:00
parent 54f98da930
commit fd10995478
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=285140
4 changed files with 136 additions and 28 deletions

View file

@ -396,6 +396,7 @@ int (dprintf)(int, const char * __restrict, ...);
int asprintf(char **, const char *, ...) __printflike(2, 3); int asprintf(char **, const char *, ...) __printflike(2, 3);
char *ctermid_r(char *); char *ctermid_r(char *);
void fcloseall(void); void fcloseall(void);
int fdclose(FILE *, int *);
char *fgetln(FILE *, size_t *); char *fgetln(FILE *, size_t *);
const char *fmtcheck(const char *, const char *) __format_arg(2); const char *fmtcheck(const char *, const char *) __format_arg(2);
int fpurge(FILE *); int fpurge(FILE *);

View file

@ -162,6 +162,10 @@ FBSD_1.3 {
mkostemps; mkostemps;
}; };
FBSD_1.4 {
fdclose;
};
FBSDprivate_1.0 { FBSDprivate_1.0 {
_flockfile; _flockfile;
_flockfile_debug_stub; _flockfile_debug_stub;

View file

@ -1,5 +1,6 @@
.\" Copyright (c) 1990, 1991, 1993 .\" Copyright (c) 1990, 1991, 1993 The Regents of the University of California.
.\" The Regents of the University of California. All rights reserved. .\" Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
.\" All rights reserved.
.\" .\"
.\" This code is derived from software contributed to Berkeley by .\" This code is derived from software contributed to Berkeley by
.\" Chris Torek and the American National Standards Committee X3, .\" Chris Torek and the American National Standards Committee X3,
@ -32,11 +33,12 @@
.\" @(#)fclose.3 8.1 (Berkeley) 6/4/93 .\" @(#)fclose.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd April 22, 2006 .Dd July 4, 2015
.Dt FCLOSE 3 .Dt FCLOSE 3
.Os .Os
.Sh NAME .Sh NAME
.Nm fclose , .Nm fclose ,
.Nm fdclose ,
.Nm fcloseall .Nm fcloseall
.Nd close a stream .Nd close a stream
.Sh LIBRARY .Sh LIBRARY
@ -45,6 +47,8 @@
.In stdio.h .In stdio.h
.Ft int .Ft int
.Fn fclose "FILE *stream" .Fn fclose "FILE *stream"
.Ft int
.Fn fdclose "FILE *stream" "int *fdp"
.Ft void .Ft void
.Fn fcloseall void .Fn fcloseall void
.Sh DESCRIPTION .Sh DESCRIPTION
@ -59,36 +63,77 @@ first, using
.Xr fflush 3 . .Xr fflush 3 .
.Pp .Pp
The The
.Fn fdclose
function is equivalent to
.Fn fclose
except that it does not close the underlying file descriptor.
If
.Fa fdp
is not
.Dv NULL ,
the file descriptor will be written to it.
If the
.Fa fdp
argument will be different then NULL the file descriptor will be returned in it,
If the stream does not have an associated file descriptor,
.Fa fdp
will be set to -1.
This type of stream is created with functions such as
.Xr fmemopen 3 ,
.Xr funopen 3 ,
or
.Xr open_memstream 3 .
.Pp
The
.Fn fcloseall .Fn fcloseall
function calls function calls
.Fn fclose .Fn fclose
on all open streams. on all open streams.
.Sh RETURN VALUES .Sh RETURN VALUES
Upon successful completion 0 is returned. .Fn fcloseall
does not return a value.
.Pp
Upon successful completion the
.Fn fclose
and
.Fn fdclose
functions return 0.
Otherwise, Otherwise,
.Dv EOF .Dv EOF
is returned and the global variable is returned and the global variable
.Va errno .Va errno
is set to indicate the error. is set to indicate the error.
In either case no further access to the stream is possible.
.Sh ERRORS .Sh ERRORS
.Fn fdclose
fails if:
.Bl -tag -width Er
.It Bq Er EOPNOTSUPP
The stream does not have an associated file descriptor.
.El
.Pp
The The
.Fn fclose .Fn fclose
function and
may also fail and set .Fn fdclose
functions may also fail and set
.Va errno .Va errno
for any of the errors specified for the routines for any of the errors specified for
.Xr close 2
or
.Xr fflush 3 . .Xr fflush 3 .
.Pp
The
.Fn fclose
function may also fail and set errno for any of the errors specified for
.Xr close 2 .
.Sh NOTES .Sh NOTES
The The
.Fn fclose .Fn fclose
function and
does not handle NULL arguments; they will result in a segmentation .Fn fdclose
violation. functions do not handle NULL arguments in the
This is intentional - it makes it easier to make sure programs written .Fa stream
under variable; this will result in a segmentation violation.
This is intentional.
It makes it easier to make sure programs written under
.Fx .Fx
are bug free. are bug free.
This behaviour is an implementation detail, and programs should not This behaviour is an implementation detail, and programs should not
@ -104,8 +149,13 @@ The
function function
conforms to conforms to
.St -isoC . .St -isoC .
.Pp .Sh HISTORY
The The
.Fn fcloseall .Fn fcloseall
function first appeared in function first appeared in
.Fx 7.0 . .Fx 7.0 .
.Pp
The
.Fn fdclose
function first appeared in
.Fx 11.0 .

View file

@ -1,6 +1,7 @@
/*- /*-
* Copyright (c) 1990, 1993 * Copyright (c) 1990, 1993 The Regents of the University of California.
* The Regents of the University of California. All rights reserved. * Copyright (c) 2013 Mariusz Zaborski <oshogbo@FreeBSD.org>
* All rights reserved.
* *
* This code is derived from software contributed to Berkeley by * This code is derived from software contributed to Berkeley by
* Chris Torek. * Chris Torek.
@ -38,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include "namespace.h" #include "namespace.h"
#include <errno.h> #include <errno.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "un-namespace.h" #include "un-namespace.h"
@ -45,19 +47,17 @@ __FBSDID("$FreeBSD$");
#include "libc_private.h" #include "libc_private.h"
#include "local.h" #include "local.h"
int static int
fclose(FILE *fp) cleanfile(FILE *fp, bool c)
{ {
int r; int r;
if (fp->_flags == 0) { /* not open! */
errno = EBADF;
return (EOF);
}
FLOCKFILE(fp);
r = fp->_flags & __SWR ? __sflush(fp) : 0; r = fp->_flags & __SWR ? __sflush(fp) : 0;
if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) if (c) {
r = EOF; if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
r = EOF;
}
if (fp->_flags & __SMBF) if (fp->_flags & __SMBF)
free((char *)fp->_bf._base); free((char *)fp->_bf._base);
if (HASUB(fp)) if (HASUB(fp))
@ -80,6 +80,59 @@ fclose(FILE *fp)
STDIO_THREAD_LOCK(); STDIO_THREAD_LOCK();
fp->_flags = 0; /* Release this FILE for reuse. */ fp->_flags = 0; /* Release this FILE for reuse. */
STDIO_THREAD_UNLOCK(); STDIO_THREAD_UNLOCK();
FUNLOCKFILE(fp);
return (r);
}
int
fdclose(FILE *fp, int *fdp)
{
int r, err;
if (fdp != NULL)
*fdp = -1;
if (fp->_flags == 0) { /* not open! */
errno = EBADF;
return (EOF);
}
FLOCKFILE(fp);
r = 0;
if (fp->_close != __sclose) {
r = EOF;
errno = EOPNOTSUPP;
} else if (fp->_file < 0) {
r = EOF;
errno = EBADF;
}
if (r == EOF) {
err = errno;
(void)cleanfile(fp, true);
errno = err;
} else {
if (fdp != NULL)
*fdp = fp->_file;
r = cleanfile(fp, false);
}
FUNLOCKFILE(fp);
return (r);
}
int
fclose(FILE *fp)
{
int r;
if (fp->_flags == 0) { /* not open! */
errno = EBADF;
return (EOF);
}
FLOCKFILE(fp);
r = cleanfile(fp, true);
FUNLOCKFILE(fp);
return (r); return (r);
} }