1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #include "sfhdr.h" 23 24 /* Close a stream. A file stream is synced before closing. 25 ** 26 ** Written by Kiem-Phong Vo 27 */ 28 29 #if __STD_C 30 int sfclose(reg Sfio_t* f) 31 #else 32 int sfclose(f) 33 reg Sfio_t* f; 34 #endif 35 { 36 reg int local, ex, rv; 37 Void_t* data = NIL(Void_t*); 38 39 SFMTXSTART(f, -1); 40 41 GETLOCAL(f,local); 42 43 if(!(f->mode&SF_INIT) && 44 SFMODE(f,local) != (f->mode&SF_RDWR) && 45 SFMODE(f,local) != (f->mode&(SF_READ|SF_SYNCED)) && 46 _sfmode(f,SF_SYNCED,local) < 0) 47 SFMTXRETURN(f,-1); 48 49 /* closing a stack of streams */ 50 while(f->push) 51 { reg Sfio_t* pop; 52 53 if(!(pop = (*_Sfstack)(f,NIL(Sfio_t*))) ) 54 SFMTXRETURN(f,-1); 55 if(sfclose(pop) < 0) 56 { (*_Sfstack)(f,pop); 57 SFMTXRETURN(f,-1); 58 } 59 } 60 61 rv = 0; 62 if(f->disc == _Sfudisc) /* closing the ungetc stream */ 63 f->disc = NIL(Sfdisc_t*); 64 else if(f->file >= 0) /* sync file pointer */ 65 { f->bits |= SF_ENDING; 66 rv = sfsync(f); 67 } 68 69 SFLOCK(f,0); 70 71 /* raise discipline exceptions */ 72 if(f->disc && (ex = SFRAISE(f,local ? SF_NEW : SF_CLOSING,NIL(Void_t*))) != 0) 73 SFMTXRETURN(f,ex); 74 75 if(!local && f->pool) 76 { /* remove from pool */ 77 if(f->pool == &_Sfpool) 78 { reg int n; 79 80 POOLMTXLOCK(&_Sfpool); 81 for(n = 0; n < _Sfpool.n_sf; ++n) 82 { if(_Sfpool.sf[n] != f) 83 continue; 84 /* found it */ 85 _Sfpool.n_sf -= 1; 86 for(; n < _Sfpool.n_sf; ++n) 87 _Sfpool.sf[n] = _Sfpool.sf[n+1]; 88 break; 89 } 90 POOLMTXUNLOCK(&_Sfpool); 91 } 92 else 93 { f->mode &= ~SF_LOCK; /**/ASSERT(_Sfpmove); 94 if((*_Sfpmove)(f,-1) < 0) 95 { SFOPEN(f,0); 96 SFMTXRETURN(f,-1); 97 } 98 f->mode |= SF_LOCK; 99 } 100 f->pool = NIL(Sfpool_t*); 101 } 102 103 if(f->data && (!local || (f->flags&SF_STRING) || (f->bits&SF_MMAP) ) ) 104 { /* free buffer */ 105 #ifdef MAP_TYPE 106 if(f->bits&SF_MMAP) 107 SFMUNMAP(f,f->data,f->endb-f->data); 108 else 109 #endif 110 if(f->flags&SF_MALLOC) 111 data = (Void_t*)f->data; 112 113 f->data = NIL(uchar*); 114 f->size = -1; 115 } 116 117 /* zap the file descriptor */ 118 if(_Sfnotify) 119 (*_Sfnotify)(f,SF_CLOSING,f->file); 120 if(f->file >= 0 && !(f->flags&SF_STRING)) 121 CLOSE(f->file); 122 f->file = -1; 123 124 SFKILL(f); 125 f->flags &= SF_STATIC; 126 f->here = 0; 127 f->extent = -1; 128 f->endb = f->endr = f->endw = f->next = f->data; 129 130 /* zap any associated auxiliary buffer */ 131 if(f->rsrv) 132 { free(f->rsrv); 133 f->rsrv = NIL(Sfrsrv_t*); 134 } 135 136 /* delete any associated sfpopen-data */ 137 if(f->proc) 138 rv = _sfpclose(f); 139 140 /* destroy the mutex */ 141 if(f->mutex) 142 { (void)vtmtxclrlock(f->mutex); 143 if(f != sfstdin && f != sfstdout && f != sfstderr) 144 { (void)vtmtxclose(f->mutex); 145 f->mutex = NIL(Vtmutex_t*); 146 } 147 } 148 149 if(!local) 150 { if(f->disc && (ex = SFRAISE(f,SF_FINAL,NIL(Void_t*))) != 0 ) 151 { rv = ex; 152 goto done; 153 } 154 155 if(!(f->flags&SF_STATIC) ) 156 free(f); 157 else 158 { f->disc = NIL(Sfdisc_t*); 159 f->stdio = NIL(Void_t*); 160 f->mode = SF_AVAIL; 161 } 162 } 163 164 done: 165 if(data) 166 free(data); 167 return rv; 168 } 169