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 <stdio.h>
53 #include <stdlib.h>
54 #include <sys/lock.h>
55 #include "local.h"
56
57 int
fclose(register FILE * fp)58 fclose (
59 register FILE * fp)
60 {
61 int r;
62
63 if (fp == NULL)
64 return (0); /* on NULL */
65
66 CHECK_INIT (rptr, fp);
67
68 /* We can't use the _newlib_flockfile_XXX macros here due to the
69 interlocked locking with the sfp_lock. */
70 #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
71 int __oldcancel;
72 pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldcancel);
73 #endif
74 if (!(fp->_flags2 & __SNLK))
75 _flockfile (fp);
76
77 if (fp->_flags == 0) /* not open! */
78 {
79 if (!(fp->_flags2 & __SNLK))
80 _funlockfile (fp);
81 #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
82 pthread_setcancelstate (__oldcancel, &__oldcancel);
83 #endif
84 return (0);
85 }
86 #ifdef _STDIO_BSD_SEMANTICS
87 /* BSD and Glibc systems only flush streams which have been written to. */
88 r = (fp->_flags & __SWR) ? _sflush ( fp) : 0;
89 #else
90 /* Follow POSIX semantics exactly. Unconditionally flush to allow
91 special handling for seekable read files to reposition file to last
92 byte processed as opposed to last byte read ahead into the buffer. */
93 r = _sflush ( fp);
94 #endif
95 if (fp->_close != NULL && fp->_close (fp->_cookie) < 0)
96 r = EOF;
97 if (fp->_flags & __SMBF)
98 free ((char *) fp->_bf._base);
99 if (HASUB (fp))
100 FREEUB (rptr, fp);
101 if (HASLB (fp))
102 FREELB (rptr, fp);
103 __sfp_lock_acquire ();
104 fp->_flags = 0; /* release this FILE for reuse */
105 if (!(fp->_flags2 & __SNLK))
106 _funlockfile (fp);
107 #ifndef __SINGLE_THREAD__
108 __lock_close_recursive (fp->_lock);
109 #endif
110
111 __sfp_lock_release ();
112 #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
113 pthread_setcancelstate (__oldcancel, &__oldcancel);
114 #endif
115
116 return (r);
117 }
118