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