microblaze: sync sysdep-cancel.h/sydep.h with GNU libc
[uclibc-ng.git] / libc / stdio / fclose.c
blob26b27c8cfe1fd56dbb956e63291fbbd391600d87
1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
3 * GNU Library General Public License (LGPL) version 2 or later.
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
6 */
8 #include "_stdio.h"
11 int fclose(register FILE *stream)
13 int rv = 0;
14 __STDIO_AUTO_THREADLOCK_VAR;
16 #ifdef __STDIO_HAS_OPENLIST
17 #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS)
18 /* First, remove the file from the open file list. */
20 FILE *ptr;
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;
33 ptr = ptr->__nextopen;
36 __STDIO_THREADUNLOCK_OPENLIST_ADD;
37 __STDIO_THREADUNLOCK_OPENLIST_DEL;
39 #endif
40 #endif
42 __STDIO_AUTO_THREADLOCK(stream);
44 __STDIO_STREAM_VALIDATE(stream);
46 #ifdef __STDIO_BUFFERS
47 /* Write any pending buffered chars. */
48 if (__STDIO_STREAM_IS_WRITING(stream)) {
49 rv = fflush_unlocked(stream);
51 #endif
53 if (__CLOSE(stream) < 0) { /* Must close even if fflush failed. */
54 rv = EOF;
57 stream->__filedes = -1;
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);
71 #ifndef NDEBUG
72 /* Reinitialize everything (including putc since fflush could fail). */
73 __STDIO_STREAM_DISABLE_GETC(stream);
74 __STDIO_STREAM_DISABLE_PUTC(stream);
75 __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
77 # ifdef __UCLIBC_HAS_WCHAR__
78 stream->__ungot_width[0] = 0;
79 # endif
80 # ifdef __STDIO_MBSTATE
81 __INIT_MBSTATE(&(stream->__state));
82 # endif
83 #endif
85 __STDIO_AUTO_THREADUNLOCK(stream);
87 __STDIO_STREAM_FREE_BUFFER(stream);
88 #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
89 /* inefficient - locks/unlocks twice and walks whole list */
90 __STDIO_OPENLIST_INC_DEL_CNT;
91 __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */
92 #else
93 __STDIO_STREAM_FREE_FILE(stream);
94 #endif
96 return rv;
98 libc_hidden_def(fclose)