mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-14 20:37:06 +00:00
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:
parent
54f98da930
commit
fd10995478
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=285140
|
@ -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 *);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 .
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue