xref: /titanic_50/usr/src/lib/libast/common/sfio/sfclose.c (revision 33f2fefd46350ca5992567761c46a5b70f864340)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2008 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
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(Sfio_t* f)
31 #else
32 int sfclose(f)
33 Sfio_t*	f;
34 #endif
35 {
36 	reg int		local, ex, rv;
37 	Void_t*		data = NIL(Void_t*);
38 	SFMTXDECL(f);
39 
40 	SFMTXENTER(f, -1);
41 
42 	GETLOCAL(f,local);
43 
44 	if(!(f->mode&SF_INIT) &&
45 	   SFMODE(f,local) != (f->mode&SF_RDWR) &&
46 	   SFMODE(f,local) != (f->mode&(SF_READ|SF_SYNCED)) &&
47 	   _sfmode(f,SF_SYNCED,local) < 0)
48 		SFMTXRETURN(f,-1);
49 
50 	/* closing a stack of streams */
51 	while(f->push)
52 	{	reg Sfio_t*	pop;
53 
54 		if(!(pop = (*_Sfstack)(f,NIL(Sfio_t*))) )
55 			SFMTXRETURN(f,-1);
56 
57 		if(sfclose(pop) < 0)
58 		{	(*_Sfstack)(f,pop);
59 			SFMTXRETURN(f,-1);
60 		}
61 	}
62 
63 	rv = 0;
64 	if(f->disc == _Sfudisc)	/* closing the ungetc stream */
65 		f->disc = NIL(Sfdisc_t*);
66 	else if(f->file >= 0)	/* sync file pointer */
67 	{	f->bits |= SF_ENDING;
68 		rv = sfsync(f);
69 	}
70 
71 	SFLOCK(f,0);
72 
73 	/* raise discipline exceptions */
74 	if(f->disc && (ex = SFRAISE(f,local ? SF_NEW : SF_CLOSING,NIL(Void_t*))) != 0)
75 		SFMTXRETURN(f,ex);
76 
77 	if(!local && f->pool)
78 	{	/* remove from pool */
79 		if(f->pool == &_Sfpool)
80 		{	reg int	n;
81 
82 			POOLMTXLOCK(&_Sfpool);
83 			for(n = 0; n < _Sfpool.n_sf; ++n)
84 			{	if(_Sfpool.sf[n] != f)
85 					continue;
86 				/* found it */
87 				_Sfpool.n_sf -= 1;
88 				for(; n < _Sfpool.n_sf; ++n)
89 					_Sfpool.sf[n] = _Sfpool.sf[n+1];
90 				break;
91 			}
92 			POOLMTXUNLOCK(&_Sfpool);
93 		}
94 		else
95 		{	f->mode &= ~SF_LOCK;	/**/ASSERT(_Sfpmove);
96 			if((*_Sfpmove)(f,-1) < 0)
97 			{	SFOPEN(f,0);
98 				SFMTXRETURN(f,-1);
99 			}
100 			f->mode |= SF_LOCK;
101 		}
102 		f->pool = NIL(Sfpool_t*);
103 	}
104 
105 	if(f->data && (!local || (f->flags&SF_STRING) || (f->bits&SF_MMAP) ) )
106 	{	/* free buffer */
107 #ifdef MAP_TYPE
108 		if(f->bits&SF_MMAP)
109 			SFMUNMAP(f,f->data,f->endb-f->data);
110 		else
111 #endif
112 		if(f->flags&SF_MALLOC)
113 			data = (Void_t*)f->data;
114 
115 		f->data = NIL(uchar*);
116 		f->size = -1;
117 	}
118 
119 	/* zap the file descriptor */
120 	if(_Sfnotify)
121 		(*_Sfnotify)(f, SF_CLOSING, (void*)((long)f->file));
122 	if(f->file >= 0 && !(f->flags&SF_STRING))
123 		CLOSE(f->file);
124 	f->file = -1;
125 
126 	SFKILL(f);
127 	f->flags &= SF_STATIC;
128 	f->here = 0;
129 	f->extent = -1;
130 	f->endb = f->endr = f->endw = f->next = f->data;
131 
132 	/* zap any associated auxiliary buffer */
133 	if(f->rsrv)
134 	{	free(f->rsrv);
135 		f->rsrv = NIL(Sfrsrv_t*);
136 	}
137 
138 	/* delete any associated sfpopen-data */
139 	if(f->proc)
140 		rv = _sfpclose(f);
141 
142 	/* destroy the mutex */
143 	if(f->mutex)
144 	{	(void)vtmtxclrlock(f->mutex);
145 		if(f != sfstdin && f != sfstdout && f != sfstderr)
146 		{	(void)vtmtxclose(f->mutex);
147 			f->mutex = NIL(Vtmutex_t*);
148 		}
149 	}
150 
151 	if(!local)
152 	{	if(f->disc && (ex = SFRAISE(f,SF_FINAL,NIL(Void_t*))) != 0 )
153 		{	rv = ex;
154 			goto done;
155 		}
156 
157 		if(!(f->flags&SF_STATIC) )
158 			free(f);
159 		else
160 		{	f->disc = NIL(Sfdisc_t*);
161 			f->stdio = NIL(Void_t*);
162 			f->mode = SF_AVAIL;
163 		}
164 	}
165 
166 done:
167 	if(data)
168 		free(data);
169 	return rv;
170 }
171