158f0484fSRodney W. Grimes /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 4fd109954SMariusz Zaborski * Copyright (c) 1990, 1993 The Regents of the University of California. 5fd109954SMariusz Zaborski * Copyright (c) 2013 Mariusz Zaborski <oshogbo@FreeBSD.org> 6fd109954SMariusz Zaborski * All rights reserved. 758f0484fSRodney W. Grimes * 858f0484fSRodney W. Grimes * This code is derived from software contributed to Berkeley by 958f0484fSRodney W. Grimes * Chris Torek. 1058f0484fSRodney W. Grimes * 1158f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 1258f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 1358f0484fSRodney W. Grimes * are met: 1458f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1558f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1658f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1758f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1858f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 191d8053c5SEd Maste * 3. Neither the name of the University nor the names of its contributors 2058f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 2158f0484fSRodney W. Grimes * without specific prior written permission. 2258f0484fSRodney W. Grimes * 2358f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2458f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2558f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2658f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2758f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2858f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2958f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3058f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3158f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3258f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3358f0484fSRodney W. Grimes * SUCH DAMAGE. 3458f0484fSRodney W. Grimes */ 3558f0484fSRodney W. Grimes 3658f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 3758f0484fSRodney W. Grimes static char sccsid[] = "@(#)fclose.c 8.1 (Berkeley) 6/4/93"; 3858f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 39333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 40333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 4158f0484fSRodney W. Grimes 42d201fe46SDaniel Eischen #include "namespace.h" 4358f0484fSRodney W. Grimes #include <errno.h> 44fd109954SMariusz Zaborski #include <stdbool.h> 4558f0484fSRodney W. Grimes #include <stdio.h> 4658f0484fSRodney W. Grimes #include <stdlib.h> 47d201fe46SDaniel Eischen #include "un-namespace.h" 4846ffdf3bSKonstantin Belousov #include <spinlock.h> 49ec216c26SJohn Birrell #include "libc_private.h" 50d201fe46SDaniel Eischen #include "local.h" 5158f0484fSRodney W. Grimes 52fd109954SMariusz Zaborski static int 53fd109954SMariusz Zaborski cleanfile(FILE *fp, bool c) 5458f0484fSRodney W. Grimes { 55d201fe46SDaniel Eischen int r; 5658f0484fSRodney W. Grimes 5758f0484fSRodney W. Grimes r = fp->_flags & __SWR ? __sflush(fp) : 0; 58fd109954SMariusz Zaborski if (c) { 5958f0484fSRodney W. Grimes if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) 6058f0484fSRodney W. Grimes r = EOF; 61fd109954SMariusz Zaborski } 62fd109954SMariusz Zaborski 6358f0484fSRodney W. Grimes if (fp->_flags & __SMBF) 6458f0484fSRodney W. Grimes free((char *)fp->_bf._base); 6558f0484fSRodney W. Grimes if (HASUB(fp)) 6658f0484fSRodney W. Grimes FREEUB(fp); 6758f0484fSRodney W. Grimes if (HASLB(fp)) 6858f0484fSRodney W. Grimes FREELB(fp); 69f70177e7SJulian Elischer fp->_file = -1; 7058f0484fSRodney W. Grimes fp->_r = fp->_w = 0; /* Mess up if reaccessed. */ 7146ffdf3bSKonstantin Belousov 7246ffdf3bSKonstantin Belousov /* 7346ffdf3bSKonstantin Belousov * Lock the spinlock used to protect __sglue list walk in 7446ffdf3bSKonstantin Belousov * __sfp(). The __sfp() uses fp->_flags == 0 test as an 7546ffdf3bSKonstantin Belousov * indication of the unused FILE. 7646ffdf3bSKonstantin Belousov * 7746ffdf3bSKonstantin Belousov * Taking the lock prevents possible compiler or processor 7846ffdf3bSKonstantin Belousov * reordering of the writes performed before the final _flags 7946ffdf3bSKonstantin Belousov * cleanup, making sure that we are done with the FILE before 8046ffdf3bSKonstantin Belousov * it is considered available. 8146ffdf3bSKonstantin Belousov */ 8246ffdf3bSKonstantin Belousov STDIO_THREAD_LOCK(); 83dcd26325SDmitrij Tejblum fp->_flags = 0; /* Release this FILE for reuse. */ 8446ffdf3bSKonstantin Belousov STDIO_THREAD_UNLOCK(); 85fd109954SMariusz Zaborski 86fd109954SMariusz Zaborski return (r); 87fd109954SMariusz Zaborski } 88fd109954SMariusz Zaborski 89fd109954SMariusz Zaborski int 90fd109954SMariusz Zaborski fdclose(FILE *fp, int *fdp) 91fd109954SMariusz Zaborski { 92fd109954SMariusz Zaborski int r, err; 93fd109954SMariusz Zaborski 94fd109954SMariusz Zaborski if (fdp != NULL) 95fd109954SMariusz Zaborski *fdp = -1; 96fd109954SMariusz Zaborski 97fd109954SMariusz Zaborski if (fp->_flags == 0) { /* not open! */ 98fd109954SMariusz Zaborski errno = EBADF; 99fd109954SMariusz Zaborski return (EOF); 100fd109954SMariusz Zaborski } 101fd109954SMariusz Zaborski 102fda0a14fSKonstantin Belousov FLOCKFILE_CANCELSAFE(fp); 103fd109954SMariusz Zaborski r = 0; 104fd109954SMariusz Zaborski if (fp->_close != __sclose) { 105fd109954SMariusz Zaborski r = EOF; 106fd109954SMariusz Zaborski errno = EOPNOTSUPP; 107fd109954SMariusz Zaborski } else if (fp->_file < 0) { 108fd109954SMariusz Zaborski r = EOF; 109fd109954SMariusz Zaborski errno = EBADF; 110fd109954SMariusz Zaborski } 111fd109954SMariusz Zaborski if (r == EOF) { 112fd109954SMariusz Zaborski err = errno; 113fd109954SMariusz Zaborski (void)cleanfile(fp, true); 114fd109954SMariusz Zaborski errno = err; 115fd109954SMariusz Zaborski } else { 116fd109954SMariusz Zaborski if (fdp != NULL) 117fd109954SMariusz Zaborski *fdp = fp->_file; 118fd109954SMariusz Zaborski r = cleanfile(fp, false); 119fd109954SMariusz Zaborski } 120fda0a14fSKonstantin Belousov FUNLOCKFILE_CANCELSAFE(); 121fd109954SMariusz Zaborski 122fd109954SMariusz Zaborski return (r); 123fd109954SMariusz Zaborski } 124fd109954SMariusz Zaborski 125fd109954SMariusz Zaborski int 126fd109954SMariusz Zaborski fclose(FILE *fp) 127fd109954SMariusz Zaborski { 128fd109954SMariusz Zaborski int r; 129fd109954SMariusz Zaborski 130fd109954SMariusz Zaborski if (fp->_flags == 0) { /* not open! */ 131fd109954SMariusz Zaborski errno = EBADF; 132fd109954SMariusz Zaborski return (EOF); 133fd109954SMariusz Zaborski } 134fd109954SMariusz Zaborski 135fda0a14fSKonstantin Belousov FLOCKFILE_CANCELSAFE(fp); 136fd109954SMariusz Zaborski r = cleanfile(fp, true); 137fda0a14fSKonstantin Belousov FUNLOCKFILE_CANCELSAFE(); 138fd109954SMariusz Zaborski 13958f0484fSRodney W. Grimes return (r); 14058f0484fSRodney W. Grimes } 141