summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2015-12-01 18:19:23 +0000
committerngie <ngie@FreeBSD.org>2015-12-01 18:19:23 +0000
commitf2f170ddd8d54aa95c75879e4e329feaf19ef119 (patch)
treecba970673e1ceed9b626c0054c7fce1f318a3d68 /lib
parentff68307fb48ebed764757b9f0ff301df2f3d8825 (diff)
downloadFreeBSD-src-f2f170ddd8d54aa95c75879e4e329feaf19ef119.zip
FreeBSD-src-f2f170ddd8d54aa95c75879e4e329feaf19ef119.tar.gz
MFC r285140:
r285140 (by oshogbo): 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
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdio/Symbol.map4
-rw-r--r--lib/libc/stdio/fclose.382
-rw-r--r--lib/libc/stdio/fclose.c75
3 files changed, 134 insertions, 27 deletions
diff --git a/lib/libc/stdio/Symbol.map b/lib/libc/stdio/Symbol.map
index d2a8c92..a332ab2 100644
--- a/lib/libc/stdio/Symbol.map
+++ b/lib/libc/stdio/Symbol.map
@@ -162,6 +162,10 @@ FBSD_1.3 {
mkostemps;
};
+FBSD_1.4 {
+ fdclose;
+};
+
FBSDprivate_1.0 {
_flockfile;
_flockfile_debug_stub;
diff --git a/lib/libc/stdio/fclose.3 b/lib/libc/stdio/fclose.3
index 883aa10..596ee3d 100644
--- a/lib/libc/stdio/fclose.3
+++ b/lib/libc/stdio/fclose.3
@@ -1,5 +1,6 @@
-.\" Copyright (c) 1990, 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 1990, 1991, 1993 The Regents of the University of California.
+.\" Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
+.\" All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Chris Torek and the American National Standards Committee X3,
@@ -32,11 +33,12 @@
.\" @(#)fclose.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd April 22, 2006
+.Dd July 4, 2015
.Dt FCLOSE 3
.Os
.Sh NAME
.Nm fclose ,
+.Nm fdclose ,
.Nm fcloseall
.Nd close a stream
.Sh LIBRARY
@@ -45,6 +47,8 @@
.In stdio.h
.Ft int
.Fn fclose "FILE *stream"
+.Ft int
+.Fn fdclose "FILE *stream" "int *fdp"
.Ft void
.Fn fcloseall void
.Sh DESCRIPTION
@@ -59,36 +63,77 @@ first, using
.Xr fflush 3 .
.Pp
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
function calls
.Fn fclose
on all open streams.
.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,
.Dv EOF
is returned and the global variable
.Va errno
is set to indicate the error.
-In either case no further access to the stream is possible.
.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
.Fn fclose
-function
-may also fail and set
+and
+.Fn fdclose
+functions may also fail and set
.Va errno
-for any of the errors specified for the routines
-.Xr close 2
-or
+for any of the errors specified for
.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
The
.Fn fclose
-function
-does not handle NULL arguments; they will result in a segmentation
-violation.
-This is intentional - it makes it easier to make sure programs written
-under
+and
+.Fn fdclose
+functions do not handle NULL arguments in the
+.Fa stream
+variable; this will result in a segmentation violation.
+This is intentional.
+It makes it easier to make sure programs written under
.Fx
are bug free.
This behaviour is an implementation detail, and programs should not
@@ -104,8 +149,13 @@ The
function
conforms to
.St -isoC .
-.Pp
+.Sh HISTORY
The
.Fn fcloseall
function first appeared in
.Fx 7.0 .
+.Pp
+The
+.Fn fdclose
+function first appeared in
+.Fx 11.0 .
diff --git a/lib/libc/stdio/fclose.c b/lib/libc/stdio/fclose.c
index 5ed8b2c..24b9b90 100644
--- a/lib/libc/stdio/fclose.c
+++ b/lib/libc/stdio/fclose.c
@@ -1,6 +1,7 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1990, 1993 The Regents of the University of California.
+ * Copyright (c) 2013 Mariusz Zaborski <oshogbo@FreeBSD.org>
+ * All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
@@ -38,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include "namespace.h"
#include <errno.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "un-namespace.h"
@@ -45,19 +47,17 @@ __FBSDID("$FreeBSD$");
#include "libc_private.h"
#include "local.h"
-int
-fclose(FILE *fp)
+static int
+cleanfile(FILE *fp, bool c)
{
int r;
- if (fp->_flags == 0) { /* not open! */
- errno = EBADF;
- return (EOF);
- }
- FLOCKFILE(fp);
r = fp->_flags & __SWR ? __sflush(fp) : 0;
- if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
- r = EOF;
+ if (c) {
+ if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
+ r = EOF;
+ }
+
if (fp->_flags & __SMBF)
free((char *)fp->_bf._base);
if (HASUB(fp))
@@ -80,6 +80,59 @@ fclose(FILE *fp)
STDIO_THREAD_LOCK();
fp->_flags = 0; /* Release this FILE for reuse. */
STDIO_THREAD_UNLOCK();
+
+ 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);
}
OpenPOWER on IntegriCloud