11573Srgrimes/*- 2291602Sngie * Copyright (c) 1990, 1993 The Regents of the University of California. 3291602Sngie * Copyright (c) 2013 Mariusz Zaborski <oshogbo@FreeBSD.org> 4291602Sngie * All rights reserved. 51573Srgrimes * 61573Srgrimes * This code is derived from software contributed to Berkeley by 71573Srgrimes * Chris Torek. 81573Srgrimes * 91573Srgrimes * Redistribution and use in source and binary forms, with or without 101573Srgrimes * modification, are permitted provided that the following conditions 111573Srgrimes * are met: 121573Srgrimes * 1. Redistributions of source code must retain the above copyright 131573Srgrimes * notice, this list of conditions and the following disclaimer. 141573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151573Srgrimes * notice, this list of conditions and the following disclaimer in the 161573Srgrimes * documentation and/or other materials provided with the distribution. 17249808Semaste * 3. Neither the name of the University nor the names of its contributors 181573Srgrimes * may be used to endorse or promote products derived from this software 191573Srgrimes * without specific prior written permission. 201573Srgrimes * 211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311573Srgrimes * SUCH DAMAGE. 321573Srgrimes */ 331573Srgrimes 341573Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 351573Srgrimesstatic char sccsid[] = "@(#)fclose.c 8.1 (Berkeley) 6/4/93"; 361573Srgrimes#endif /* LIBC_SCCS and not lint */ 3792986Sobrien#include <sys/cdefs.h> 3892986Sobrien__FBSDID("$FreeBSD: stable/10/lib/libc/stdio/fclose.c 321074 2017-07-17 14:09:34Z kib $"); 391573Srgrimes 4071579Sdeischen#include "namespace.h" 411573Srgrimes#include <errno.h> 42291602Sngie#include <stdbool.h> 431573Srgrimes#include <stdio.h> 441573Srgrimes#include <stdlib.h> 4571579Sdeischen#include "un-namespace.h" 46234657Skib#include <spinlock.h> 4771579Sdeischen#include "libc_private.h" 481573Srgrimes#include "local.h" 491573Srgrimes 50291602Sngiestatic int 51291602Sngiecleanfile(FILE *fp, bool c) 521573Srgrimes{ 5371579Sdeischen int r; 541573Srgrimes 55291602Sngie r = fp->_flags & __SWR ? __sflush(fp) : 0; 56291602Sngie if (c) { 57291602Sngie if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) 58291602Sngie r = EOF; 591573Srgrimes } 60291602Sngie 611573Srgrimes if (fp->_flags & __SMBF) 621573Srgrimes free((char *)fp->_bf._base); 631573Srgrimes if (HASUB(fp)) 641573Srgrimes FREEUB(fp); 651573Srgrimes if (HASLB(fp)) 661573Srgrimes FREELB(fp); 6713545Sjulian fp->_file = -1; 681573Srgrimes fp->_r = fp->_w = 0; /* Mess up if reaccessed. */ 69234657Skib 70234657Skib /* 71234657Skib * Lock the spinlock used to protect __sglue list walk in 72234657Skib * __sfp(). The __sfp() uses fp->_flags == 0 test as an 73234657Skib * indication of the unused FILE. 74234657Skib * 75234657Skib * Taking the lock prevents possible compiler or processor 76234657Skib * reordering of the writes performed before the final _flags 77234657Skib * cleanup, making sure that we are done with the FILE before 78234657Skib * it is considered available. 79234657Skib */ 80234657Skib STDIO_THREAD_LOCK(); 8153529Sdt fp->_flags = 0; /* Release this FILE for reuse. */ 82234657Skib STDIO_THREAD_UNLOCK(); 83291602Sngie 84291602Sngie return (r); 85291602Sngie} 86291602Sngie 87291602Sngieint 88291602Sngiefdclose(FILE *fp, int *fdp) 89291602Sngie{ 90291602Sngie int r, err; 91291602Sngie 92291602Sngie if (fdp != NULL) 93291602Sngie *fdp = -1; 94291602Sngie 95291602Sngie if (fp->_flags == 0) { /* not open! */ 96291602Sngie errno = EBADF; 97291602Sngie return (EOF); 98291602Sngie } 99291602Sngie 100321074Skib FLOCKFILE_CANCELSAFE(fp); 101291602Sngie r = 0; 102291602Sngie if (fp->_close != __sclose) { 103291602Sngie r = EOF; 104291602Sngie errno = EOPNOTSUPP; 105291602Sngie } else if (fp->_file < 0) { 106291602Sngie r = EOF; 107291602Sngie errno = EBADF; 108291602Sngie } 109291602Sngie if (r == EOF) { 110291602Sngie err = errno; 111291602Sngie (void)cleanfile(fp, true); 112291602Sngie errno = err; 113291602Sngie } else { 114291602Sngie if (fdp != NULL) 115291602Sngie *fdp = fp->_file; 116291602Sngie r = cleanfile(fp, false); 117291602Sngie } 118321074Skib FUNLOCKFILE_CANCELSAFE(); 119291602Sngie 1201573Srgrimes return (r); 1211573Srgrimes} 122291602Sngie 123291602Sngieint 124291602Sngiefclose(FILE *fp) 125291602Sngie{ 126291602Sngie int r; 127291602Sngie 128291602Sngie if (fp->_flags == 0) { /* not open! */ 129291602Sngie errno = EBADF; 130291602Sngie return (EOF); 131291602Sngie } 132291602Sngie 133321074Skib FLOCKFILE_CANCELSAFE(fp); 134291602Sngie r = cleanfile(fp, true); 135321074Skib FUNLOCKFILE_CANCELSAFE(); 136291602Sngie 137291602Sngie return (r); 138291602Sngie} 139