]> pd.if.org Git - pdclib/blob - functions/stdio/fclose.c
8808171e745f84c67c28ed2b7f97316d65dbda92
[pdclib] / functions / stdio / fclose.c
1 /* fclose( FILE * )
2
3    This file is part of the Public Domain C Library (PDCLib).
4    Permission is granted to use, modify, and / or redistribute at will.
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <errno.h>
10
11 #ifndef REGTEST
12 #include <_PDCLIB_io.h>
13 #include <threads.h>
14
15 extern FILE * _PDCLIB_filelist;
16
17 int fclose( FILE * stream )
18 {
19     FILE * current = _PDCLIB_filelist;
20     FILE * previous = NULL;
21     /* Checking that the FILE handle is actually one we had opened before. */
22     while ( current != NULL )
23     {
24         if ( stream == current )
25         {
26             /* Flush buffer */
27             if ( stream->status & _PDCLIB_FWRITE )
28             {
29                 if ( _PDCLIB_flushbuffer( stream ) == EOF )
30                 {
31                     /* Flush failed, errno already set */
32                     return EOF;
33                 }
34             }
35
36             /* Release mutex*/
37             mtx_destroy( &stream->lock );
38
39             /* Close handle */
40             stream->ops->close(stream->handle);
41
42             /* Remove stream from list */
43             if ( previous != NULL )
44             {
45                 previous->next = stream->next;
46             }
47             else
48             {
49                 _PDCLIB_filelist = stream->next;
50             }
51             /* Delete tmpfile() */
52             if ( stream->status & _PDCLIB_DELONCLOSE )
53             {
54                 remove( stream->filename );
55             }
56             /* Free user buffer (SetVBuf allocated) */
57             if ( stream->status & _PDCLIB_FREEBUFFER )
58             {
59                 free( stream->buffer );
60             }
61             /* Free stream */
62             if ( ! ( stream->status & _PDCLIB_STATIC ) )
63             {
64                 free( stream );
65             }
66             return 0;
67         }
68         previous = current;
69         current = current->next;
70     }
71
72     errno = EINVAL;
73     return -1;
74 }
75
76 #endif
77
78 #ifdef TEST
79 #include <_PDCLIB_test.h>
80
81 int main( void )
82 {
83 #ifndef REGTEST
84     FILE * file1;
85     FILE * file2;
86     remove( testfile1 );
87     remove( testfile2 );
88     TESTCASE( _PDCLIB_filelist == stdin );
89     TESTCASE( ( file1 = fopen( testfile1, "w" ) ) != NULL );
90     TESTCASE( _PDCLIB_filelist == file1 );
91     TESTCASE( ( file2 = fopen( testfile2, "w" ) ) != NULL );
92     TESTCASE( _PDCLIB_filelist == file2 );
93     TESTCASE( fclose( file2 ) == 0 );
94     TESTCASE( _PDCLIB_filelist == file1 );
95     TESTCASE( ( file2 = fopen( testfile2, "w" ) ) != NULL );
96     TESTCASE( _PDCLIB_filelist == file2 );
97     TESTCASE( fclose( file1 ) == 0 );
98     TESTCASE( _PDCLIB_filelist == file2 );
99     TESTCASE( fclose( file2 ) == 0 );
100     TESTCASE( _PDCLIB_filelist == stdin );
101     TESTCASE( remove( testfile1 ) == 0 );
102     TESTCASE( remove( testfile2 ) == 0 );
103 #else
104     puts( " NOTEST fclose() test driver is PDCLib-specific." );
105 #endif
106     return TEST_RESULTS;
107 }
108
109 #endif
110