1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * and/or other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18 /*
19 FUNCTION
20 <<fclose>>---close a file
21
22 INDEX
23 fclose
24 INDEX
25 _fclose_r
26
27 SYNOPSIS
28 #include <stdio.h>
29 int fclose(FILE *<[fp]>);
30 int fclose( FILE *<[fp]>);
31
32 DESCRIPTION
33 If the file or stream identified by <[fp]> is open, <<fclose>> closes
34 it, after first ensuring that any pending data is written (by calling
35 <<fflush(<[fp]>)>>).
36
37 The alternate function <<_fclose_r>> is a reentrant version.
38 The extra argument <[reent]> is a pointer to a reentrancy structure.
39
40 RETURNS
41 <<fclose>> returns <<0>> if successful (including when <[fp]> is
42 <<NULL>> or not an open file); otherwise, it returns <<EOF>>.
43
44 PORTABILITY
45 <<fclose>> is required by ANSI C.
46
47 Required OS subroutines: <<close>>, <<fstat>>, <<isatty>>, <<lseek>>,
48 <<read>>, <<sbrk>>, <<write>>.
49 */
50
51 #define _DEFAULT_SOURCE
52 #include <_ansi.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <sys/lock.h>
56 #include "local.h"
57
58 int
fclose(register FILE * fp)59 fclose (
60 register FILE * fp)
61 {
62 int r;
63
64 if (fp == NULL)
65 return (0); /* on NULL */
66
67 CHECK_INIT (rptr, fp);
68
69 /* We can't use the _newlib_flockfile_XXX macros here due to the
70 interlocked locking with the sfp_lock. */
71 #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
72 int __oldcancel;
73 pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldcancel);
74 #endif
75 if (!(fp->_flags2 & __SNLK))
76 _flockfile (fp);
77
78 if (fp->_flags == 0) /* not open! */
79 {
80 if (!(fp->_flags2 & __SNLK))
81 _funlockfile (fp);
82 #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
83 pthread_setcancelstate (__oldcancel, &__oldcancel);
84 #endif
85 return (0);
86 }
87 #ifdef _STDIO_BSD_SEMANTICS
88 /* BSD and Glibc systems only flush streams which have been written to. */
89 r = (fp->_flags & __SWR) ? _sflush ( fp) : 0;
90 #else
91 /* Follow POSIX semantics exactly. Unconditionally flush to allow
92 special handling for seekable read files to reposition file to last
93 byte processed as opposed to last byte read ahead into the buffer. */
94 r = _sflush ( fp);
95 #endif
96 if (fp->_close != NULL && fp->_close (fp->_cookie) < 0)
97 r = EOF;
98 if (fp->_flags & __SMBF)
99 free ((char *) fp->_bf._base);
100 if (HASUB (fp))
101 FREEUB (rptr, fp);
102 if (HASLB (fp))
103 FREELB (rptr, fp);
104 __sfp_lock_acquire ();
105 fp->_flags = 0; /* release this FILE for reuse */
106 if (!(fp->_flags2 & __SNLK))
107 _funlockfile (fp);
108 #ifndef __SINGLE_THREAD__
109 __lock_close_recursive (fp->_lock);
110 #endif
111
112 __sfp_lock_release ();
113 #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
114 pthread_setcancelstate (__oldcancel, &__oldcancel);
115 #endif
116
117 return (r);
118 }
119