1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org> 2 * 3 * GNU Library General Public License (LGPL) version 2 or later. 4 * 5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. 6 */ 7 8 #include "_stdio.h" 9 10 fclose(register FILE * stream)11int fclose(register FILE *stream) 12 { 13 int rv = 0; 14 __STDIO_AUTO_THREADLOCK_VAR; 15 16 #ifdef __STDIO_HAS_OPENLIST 17 #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) 18 /* First, remove the file from the open file list. */ 19 { 20 FILE *ptr; 21 22 __STDIO_THREADLOCK_OPENLIST_DEL; 23 __STDIO_THREADLOCK_OPENLIST_ADD; 24 ptr = _stdio_openlist; 25 if ((ptr = _stdio_openlist) == stream) { 26 _stdio_openlist = stream->__nextopen; 27 } else { 28 while (ptr) { 29 if (ptr->__nextopen == stream) { 30 ptr->__nextopen = stream->__nextopen; 31 break; 32 } 33 ptr = ptr->__nextopen; 34 } 35 } 36 __STDIO_THREADUNLOCK_OPENLIST_ADD; 37 __STDIO_THREADUNLOCK_OPENLIST_DEL; 38 } 39 #endif 40 #endif 41 42 __STDIO_AUTO_THREADLOCK(stream); 43 44 __STDIO_STREAM_VALIDATE(stream); 45 46 #ifdef __STDIO_BUFFERS 47 /* Write any pending buffered chars. */ 48 if (__STDIO_STREAM_IS_WRITING(stream)) { 49 rv = fflush_unlocked(stream); 50 } 51 #endif 52 53 if (__CLOSE(stream) < 0) { /* Must close even if fflush failed. */ 54 rv = EOF; 55 } 56 57 stream->__filedes = -1; 58 59 /* We need a way for freopen to know that a file has been closed. 60 * Since a file can't be both readonly and writeonly, that makes 61 * an effective signal. It also has the benefit of disabling 62 * transitions to either reading or writing. */ 63 #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) 64 /* Before we mark the file as closed, make sure we increment the openlist use count 65 * so it isn't freed under us while still cleaning up. */ 66 __STDIO_OPENLIST_INC_USE; 67 #endif 68 stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE); 69 stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY); 70 71 #ifndef NDEBUG 72 __STDIO_STREAM_RESET_GCS(stream); 73 74 /* Reinitialize everything (including putc since fflush could fail). */ 75 __STDIO_STREAM_DISABLE_GETC(stream); 76 __STDIO_STREAM_DISABLE_PUTC(stream); 77 __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); 78 79 # ifdef __UCLIBC_HAS_WCHAR__ 80 stream->__ungot_width[0] = 0; 81 # endif 82 # ifdef __STDIO_MBSTATE 83 __INIT_MBSTATE(&(stream->__state)); 84 # endif 85 #endif 86 87 __STDIO_AUTO_THREADUNLOCK(stream); 88 89 __STDIO_STREAM_FREE_BUFFER(stream); 90 #ifdef __UCLIBC_MJN3_ONLY__ 91 #warning REMINDER: inefficient - locks and unlocks twice and walks whole list 92 #endif 93 #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) 94 /* inefficient - locks/unlocks twice and walks whole list */ 95 __STDIO_OPENLIST_INC_DEL_CNT; 96 __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */ 97 #else 98 __STDIO_STREAM_FREE_FILE(stream); 99 #endif 100 101 return rv; 102 } 103 libc_hidden_def(fclose) 104