[project @ 2000-04-14 16:21:32 by rrt]
[ghc-hetmet.git] / ghc / lib / std / cbits / freeFile.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: freeFile.c,v 1.11 2000/04/14 16:21:32 rrt Exp $
5  *
6  * Giving up files
7  */
8
9 #include "Rts.h"
10 #include "stgio.h"
11
12 #if defined(HAVE_WINSOCK_H) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
13 #define USE_WINSOCK
14 #endif
15
16 #ifdef USE_WINSOCK
17 #include <winsock.h>
18 #endif
19
20
21 /* sigh, the FILEs attached to the standard descriptors are 
22    handled differently. We don't want them freed via the
23    ForeignObj finaliser, as we probably want to use these
24    before we *really* shut down (dumping stats etc.)
25 */
26 void
27 freeStdFile(StgAddr fp)
28 { return; }
29
30 void
31 freeStdFileObject(StgAddr ptr)
32
33   IOFileObject* fo = (IOFileObject*)ptr;
34   int rc;
35
36   /* Don't close the file, just flush the buffer */
37   if (fo != NULL && fo->fd != -1) {
38     if (fo->buf != NULL && (fo->flags & FILEOBJ_WRITE) && fo->bufWPtr > 0) {
39        /* Flush buffer contents */
40        do {
41          rc = writeBuffer((StgForeignPtr)fo, fo->bufWPtr);
42        } while (rc == FILEOBJ_BLOCKED_WRITE) ;
43     }
44   }
45 }
46
47 void
48 freeFileObject(StgAddr ptr)
49 {
50     /*
51      * The finaliser for the file objects embedded in Handles. The RTS
52      * assumes that the finaliser runs without problems, so all
53      * we can do here is flush buffers + close(), and hope nothing went wrong.
54      *
55      */
56
57     int rc;
58     IOFileObject* fo = (IOFileObject*)ptr;
59
60     if ( fo == NULL )
61       return;
62
63     if ( fo->fd == -1 || (rc = unlockFile(fo->fd)) ) {
64         /* If the file handle has been explicitly closed
65          * (via closeFile()), we will have given
66          * up our process lock, so we break off and just return.
67          */
68       if ( fo->buf != NULL ) {
69         free(fo->buf);
70       }
71       free(fo);
72       return;
73     }
74
75     if (fo->buf != NULL && fo->bufWPtr > 0) {
76        /* Flush buffer contents before closing underlying file */
77        fo->flags &= ~FILEOBJ_RW_WRITE | ~FILEOBJ_RW_READ;
78        flushFile(ptr);
79     }
80
81 #ifdef USE_WINSOCK
82     if ( fo->flags & FILEOBJ_WINSOCK )
83       /* Sigh - the cleanup call at the end will do this for us */
84       return;
85     rc = ( fo->flags & FILEOBJ_WINSOCK ? closesocket(fo->fd) : close(fo->fd) );
86 #else
87     rc = close(fo->fd);
88 #endif
89     /* Error or no error, we don't care.. */
90
91     if ( fo->buf != NULL ) {
92        free(fo->buf);
93     }
94     free(fo);
95
96     return;
97 }
98
99 StgAddr
100 ref_freeStdFileObject(void)
101 {
102     return (StgAddr)&freeStdFileObject;
103 }
104
105 StgAddr
106 ref_freeFileObject(void)
107 {
108     return (StgAddr)&freeFileObject;
109 }
110