[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / lib / std / cbits / closeFile.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: closeFile.c,v 1.3 1998/12/02 13:27:14 simonm Exp $
5  *
6  * hClose Runtime Support
7  */
8
9 #include "Rts.h"
10 #include "stgio.h"
11
12 StgInt __really_close_stdfiles=1;
13
14 StgInt
15 closeFile(ptr,flush_buf)
16 StgForeignPtr ptr;
17 StgInt flush_buf;
18 {
19     IOFileObject* fo = (IOFileObject*)ptr;
20     int rc = 0;
21     int unlocked=1;
22
23     /* Already closed, shouldn't occur. */
24     if ( fo == NULL ) {
25        return 0;
26     }
27
28     if ( flush_buf != 0 && (fo->flags & FILEOBJ_FLUSH) ) {
29        writeFileObject(ptr,fo->bufWPtr);
30     }
31
32     /* If the flush failed, we ignore this and soldier on.. */
33
34     if ( unlockFile(fo->fd) ) {
35       /* If the file has already been unlocked (or an entry
36          for it in the locking tables couldn't be found), could
37          mean two things:
38
39             - we're repeating an hClose on an already
40               closed file (this is likely to be a bug
41               in the implementation of hClose, as this 
42               condition should have been caught before
43               we ended up here.)
44               
45             - the file wasn't locked in the first place!
46               (file descriptors to non regular files.)
47
48          We proceed with attempting to close the file,
49          but don't flag the error should close() return
50          EBADF
51       */
52         unlocked=0;
53         
54     }
55
56     /* Closing file descriptors that refer to standard channels
57        is problematic, so we back off from doing this by default,
58        just closing them at the Handle level. If you insist on
59        closing them, setting the (global) variable 
60        __really_close_stdfiles to 0 turns off this behaviour.
61     */
62     if ( (fo->flags & FILEOBJ_STD) && __really_close_stdfiles ) {
63         ;
64
65     } else  {
66       /* Regardless of success or otherwise, the fd field gets smashed. */
67       while ( (rc = close(fo->fd)) != 0 ) {
68          /* See above unlockFile() comment */
69          if ( errno != EINTR && (!unlocked && errno != EBADF ) ) {
70             cvtErrno();
71             stdErrno();
72             fo->fd = -1;
73             return rc;
74         }
75       }
76     }
77     fo->fd = -1;
78     return 0;
79 }