xref: /onnv-gate/usr/src/lib/libast/common/sfio/sfexcept.c (revision 12068:08a39a083754)
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 /*	Function to handle io exceptions.
254887Schin **	Written by Kiem-Phong Vo
264887Schin */
274887Schin 
284887Schin #if __STD_C
_sfexcept(Sfio_t * f,int type,ssize_t io,Sfdisc_t * disc)294887Schin int _sfexcept(Sfio_t* f, int type, ssize_t io, Sfdisc_t* disc)
304887Schin #else
314887Schin int _sfexcept(f,type,io,disc)
324887Schin Sfio_t*		f;	/* stream where the exception happened */
334887Schin int		type;	/* io type that was performed */
344887Schin ssize_t		io;	/* the io return value that indicated exception */
354887Schin Sfdisc_t*	disc;	/* discipline in use */
364887Schin #endif
374887Schin {
384887Schin 	reg int		ev, local, lock;
394887Schin 	reg ssize_t	size;
404887Schin 	reg uchar*	data;
418462SApril.Chin@Sun.COM 	SFMTXDECL(f);
424887Schin 
438462SApril.Chin@Sun.COM 	SFMTXENTER(f,-1);
444887Schin 
454887Schin 	GETLOCAL(f,local);
464887Schin 	lock = f->mode&SF_LOCK;
474887Schin 
484887Schin 	if(local && io <= 0)
494887Schin 		f->flags |= io < 0 ? SF_ERROR : SF_EOF;
504887Schin 
514887Schin 	if(disc && disc->exceptf)
524887Schin 	{	/* let the stream be generally accessible for this duration */
534887Schin 		if(local && lock)
544887Schin 			SFOPEN(f,0);
554887Schin 
564887Schin 		/* so that exception handler knows what we are asking for */
574887Schin 		_Sfi = f->val = io;
584887Schin 		ev = (*(disc->exceptf))(f,type,&io,disc);
594887Schin 
604887Schin 		/* relock if necessary */
614887Schin 		if(local && lock)
624887Schin 			SFLOCK(f,0);
634887Schin 
644887Schin 		if(io > 0 && !(f->flags&SF_STRING) )
654887Schin 			SFMTXRETURN(f, ev);
664887Schin 		if(ev < 0)
674887Schin 			SFMTXRETURN(f, SF_EDONE);
684887Schin 		if(ev > 0)
694887Schin 			SFMTXRETURN(f, SF_EDISC);
704887Schin 	}
714887Schin 
724887Schin 	if(f->flags&SF_STRING)
734887Schin 	{	if(type == SF_READ)
744887Schin 			goto chk_stack;
754887Schin 		else if(type != SF_WRITE && type != SF_SEEK)
764887Schin 			SFMTXRETURN(f, SF_EDONE);
774887Schin 		if(local && io >= 0)
784887Schin 		{	if(f->size >= 0 && !(f->flags&SF_MALLOC))
794887Schin 				goto chk_stack;
804887Schin 			/* extend buffer */
814887Schin 			if((size = f->size) < 0)
824887Schin 				size = 0;
834887Schin 			if((io -= size) <= 0)
844887Schin 				io = SF_GRAIN;
854887Schin 			size = ((size+io+SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
864887Schin 			if(f->size > 0)
874887Schin 				data = (uchar*)realloc((char*)f->data,size);
884887Schin 			else	data = (uchar*)malloc(size);
894887Schin 			if(!data)
904887Schin 				goto chk_stack;
914887Schin 			f->endb = data + size;
924887Schin 			f->next = data + (f->next - f->data);
934887Schin 			f->endr = f->endw = f->data = data;
944887Schin 			f->size = size;
954887Schin 		}
964887Schin 		SFMTXRETURN(f, SF_EDISC);
974887Schin 	}
984887Schin 
994887Schin 	if(errno == EINTR)
1004887Schin 	{	if(_Sfexiting || (f->bits&SF_ENDING) ||	/* stop being a hero	*/
1014887Schin 		   (f->flags&SF_IOINTR) ) /* application requests to return	*/
1024887Schin 			SFMTXRETURN(f, SF_EDONE);
1034887Schin 
1044887Schin 		/* a normal interrupt, we can continue */
1054887Schin 		errno = 0;
1064887Schin 		f->flags &= ~(SF_EOF|SF_ERROR);
1074887Schin 		SFMTXRETURN(f, SF_ECONT);
1084887Schin 	}
1094887Schin 
1104887Schin chk_stack:
1114887Schin 	if(local && f->push &&
1124887Schin 	   ((type == SF_READ  && f->next >= f->endb) ||
1134887Schin 	    (type == SF_WRITE && f->next <= f->data)))
1144887Schin 	{	/* pop the stack */
1154887Schin 		reg Sfio_t	*pf;
1164887Schin 
1174887Schin 		if(lock)
1184887Schin 			SFOPEN(f,0);
1194887Schin 
1204887Schin 		/* pop and close */
1214887Schin 		pf = (*_Sfstack)(f,NIL(Sfio_t*));
1224887Schin 		if((ev = sfclose(pf)) < 0) /* can't close, restack */
1234887Schin 			(*_Sfstack)(f,pf);
1244887Schin 
1254887Schin 		if(lock)
1264887Schin 			SFLOCK(f,0);
1274887Schin 
1284887Schin 		ev = ev < 0 ? SF_EDONE : SF_ESTACK;
1294887Schin 	}
1304887Schin 	else	ev = SF_EDONE;
1314887Schin 
1324887Schin 	SFMTXRETURN(f, ev);
1334887Schin }
134