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.
11 int fclose(register FILE *stream
)
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. */
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
;
29 if (ptr
->__nextopen
== stream
) {
30 ptr
->__nextopen
= stream
->__nextopen
;
33 ptr
= ptr
->__nextopen
;
36 __STDIO_THREADUNLOCK_OPENLIST_ADD
;
37 __STDIO_THREADUNLOCK_OPENLIST_DEL
;
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
);
53 if (__CLOSE(stream
) < 0) { /* Must close even if fflush failed. */
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
;
68 stream
->__modeflags
&= (__FLAG_FREEBUF
|__FLAG_FREEFILE
);
69 stream
->__modeflags
|= (__FLAG_READONLY
|__FLAG_WRITEONLY
);
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;
80 # ifdef __STDIO_MBSTATE
81 __INIT_MBSTATE(&(stream
->__state
));
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. */
93 __STDIO_STREAM_FREE_FILE(stream
);
98 libc_hidden_def(fclose
)