14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #include "sfhdr.h"
234887Schin
244887Schin /* Close a stream. A file stream is synced before closing.
254887Schin **
264887Schin ** Written by Kiem-Phong Vo
274887Schin */
284887Schin
294887Schin #if __STD_C
sfclose(Sfio_t * f)308462SApril.Chin@Sun.COM int sfclose(Sfio_t* f)
314887Schin #else
324887Schin int sfclose(f)
338462SApril.Chin@Sun.COM Sfio_t* f;
344887Schin #endif
354887Schin {
364887Schin reg int local, ex, rv;
374887Schin Void_t* data = NIL(Void_t*);
388462SApril.Chin@Sun.COM SFMTXDECL(f);
394887Schin
408462SApril.Chin@Sun.COM SFMTXENTER(f, -1);
414887Schin
424887Schin GETLOCAL(f,local);
434887Schin
444887Schin if(!(f->mode&SF_INIT) &&
454887Schin SFMODE(f,local) != (f->mode&SF_RDWR) &&
464887Schin SFMODE(f,local) != (f->mode&(SF_READ|SF_SYNCED)) &&
474887Schin _sfmode(f,SF_SYNCED,local) < 0)
484887Schin SFMTXRETURN(f,-1);
494887Schin
504887Schin /* closing a stack of streams */
514887Schin while(f->push)
524887Schin { reg Sfio_t* pop;
534887Schin
544887Schin if(!(pop = (*_Sfstack)(f,NIL(Sfio_t*))) )
554887Schin SFMTXRETURN(f,-1);
568462SApril.Chin@Sun.COM
574887Schin if(sfclose(pop) < 0)
584887Schin { (*_Sfstack)(f,pop);
594887Schin SFMTXRETURN(f,-1);
604887Schin }
614887Schin }
624887Schin
634887Schin rv = 0;
644887Schin if(f->disc == _Sfudisc) /* closing the ungetc stream */
654887Schin f->disc = NIL(Sfdisc_t*);
664887Schin else if(f->file >= 0) /* sync file pointer */
674887Schin { f->bits |= SF_ENDING;
684887Schin rv = sfsync(f);
694887Schin }
704887Schin
714887Schin SFLOCK(f,0);
724887Schin
734887Schin /* raise discipline exceptions */
744887Schin if(f->disc && (ex = SFRAISE(f,local ? SF_NEW : SF_CLOSING,NIL(Void_t*))) != 0)
754887Schin SFMTXRETURN(f,ex);
764887Schin
774887Schin if(!local && f->pool)
784887Schin { /* remove from pool */
794887Schin if(f->pool == &_Sfpool)
804887Schin { reg int n;
814887Schin
824887Schin POOLMTXLOCK(&_Sfpool);
834887Schin for(n = 0; n < _Sfpool.n_sf; ++n)
844887Schin { if(_Sfpool.sf[n] != f)
854887Schin continue;
864887Schin /* found it */
874887Schin _Sfpool.n_sf -= 1;
884887Schin for(; n < _Sfpool.n_sf; ++n)
894887Schin _Sfpool.sf[n] = _Sfpool.sf[n+1];
904887Schin break;
914887Schin }
924887Schin POOLMTXUNLOCK(&_Sfpool);
934887Schin }
944887Schin else
954887Schin { f->mode &= ~SF_LOCK; /**/ASSERT(_Sfpmove);
964887Schin if((*_Sfpmove)(f,-1) < 0)
974887Schin { SFOPEN(f,0);
984887Schin SFMTXRETURN(f,-1);
994887Schin }
1004887Schin f->mode |= SF_LOCK;
1014887Schin }
1024887Schin f->pool = NIL(Sfpool_t*);
1034887Schin }
1044887Schin
1054887Schin if(f->data && (!local || (f->flags&SF_STRING) || (f->bits&SF_MMAP) ) )
1064887Schin { /* free buffer */
1074887Schin #ifdef MAP_TYPE
1084887Schin if(f->bits&SF_MMAP)
1094887Schin SFMUNMAP(f,f->data,f->endb-f->data);
1104887Schin else
1114887Schin #endif
1124887Schin if(f->flags&SF_MALLOC)
1134887Schin data = (Void_t*)f->data;
1144887Schin
1154887Schin f->data = NIL(uchar*);
1164887Schin f->size = -1;
1174887Schin }
1184887Schin
1194887Schin /* zap the file descriptor */
1204887Schin if(_Sfnotify)
1218462SApril.Chin@Sun.COM (*_Sfnotify)(f, SF_CLOSING, (void*)((long)f->file));
1224887Schin if(f->file >= 0 && !(f->flags&SF_STRING))
1234887Schin CLOSE(f->file);
1244887Schin f->file = -1;
1254887Schin
1264887Schin SFKILL(f);
1274887Schin f->flags &= SF_STATIC;
1284887Schin f->here = 0;
1294887Schin f->extent = -1;
1304887Schin f->endb = f->endr = f->endw = f->next = f->data;
1314887Schin
1324887Schin /* zap any associated auxiliary buffer */
1334887Schin if(f->rsrv)
1344887Schin { free(f->rsrv);
1354887Schin f->rsrv = NIL(Sfrsrv_t*);
1364887Schin }
1374887Schin
1384887Schin /* delete any associated sfpopen-data */
1394887Schin if(f->proc)
1404887Schin rv = _sfpclose(f);
1414887Schin
1424887Schin /* destroy the mutex */
1434887Schin if(f->mutex)
1444887Schin { (void)vtmtxclrlock(f->mutex);
1454887Schin if(f != sfstdin && f != sfstdout && f != sfstderr)
1464887Schin { (void)vtmtxclose(f->mutex);
1474887Schin f->mutex = NIL(Vtmutex_t*);
1484887Schin }
1494887Schin }
1504887Schin
1514887Schin if(!local)
1524887Schin { if(f->disc && (ex = SFRAISE(f,SF_FINAL,NIL(Void_t*))) != 0 )
1534887Schin { rv = ex;
1544887Schin goto done;
1554887Schin }
1564887Schin
1574887Schin if(!(f->flags&SF_STATIC) )
1584887Schin free(f);
1594887Schin else
1604887Schin { f->disc = NIL(Sfdisc_t*);
1614887Schin f->stdio = NIL(Void_t*);
1624887Schin f->mode = SF_AVAIL;
1634887Schin }
1644887Schin }
1654887Schin
1664887Schin done:
1674887Schin if(data)
1684887Schin free(data);
1694887Schin return rv;
1704887Schin }
171