summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio/fclose.c
diff options
context:
space:
mode:
authoroshogbo <oshogbo@FreeBSD.org>2015-07-04 16:42:14 +0000
committeroshogbo <oshogbo@FreeBSD.org>2015-07-04 16:42:14 +0000
commite1ffe0f912feb756dc9cddef6953a09a9e9d6605 (patch)
treee614562cff4421bbd6605abcd4a8622399f988f4 /lib/libc/stdio/fclose.c
parent852c8fe5892ac15db686e35cc70e512fd442325a (diff)
downloadFreeBSD-src-e1ffe0f912feb756dc9cddef6953a09a9e9d6605.zip
FreeBSD-src-e1ffe0f912feb756dc9cddef6953a09a9e9d6605.tar.gz
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/libc/stdio/fclose.c')
-rw-r--r--lib/libc/stdio/fclose.c75
1 files changed, 64 insertions, 11 deletions
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