xref: /titanic_51/usr/src/lib/libast/common/sfio/sfclose.c (revision 4e9cfc9a015e8ca7d41f7d018c74dc8a692305b3)
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