blob: 3417b267858d4514834fcc948bdc1f35a32daa79 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* 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
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}
103libc_hidden_def(fclose)