Blame src/lib/libast/sfio/sfexcept.c

Packit Service a8c26c
/***********************************************************************
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*               This software is part of the ast package               *
Packit Service a8c26c
*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
Packit Service a8c26c
*                      and is licensed under the                       *
Packit Service a8c26c
*                 Eclipse Public License, Version 1.0                  *
Packit Service a8c26c
*                    by AT&T Intellectual Property                     *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                A copy of the License is available at                 *
Packit Service a8c26c
*          http://www.eclipse.org/org/documents/epl-v10.html           *
Packit Service a8c26c
*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*              Information and Software Systems Research               *
Packit Service a8c26c
*                            AT&T Research                             *
Packit Service a8c26c
*                           Florham Park NJ                            *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                 Glenn Fowler <gsf@research.att.com>                  *
Packit Service a8c26c
*                  David Korn <dgk@research.att.com>                   *
Packit Service a8c26c
*                   Phong Vo <kpv@research.att.com>                    *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
***********************************************************************/
Packit Service a8c26c
#include	"sfhdr.h"
Packit Service a8c26c
Packit Service a8c26c
/*	Function to handle io exceptions.
Packit Service a8c26c
**	Written by Kiem-Phong Vo
Packit Service a8c26c
*/
Packit Service a8c26c
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
int _sfexcept(Sfio_t* f, int type, ssize_t io, Sfdisc_t* disc)
Packit Service a8c26c
#else
Packit Service a8c26c
int _sfexcept(f,type,io,disc)
Packit Service a8c26c
Sfio_t*		f;	/* stream where the exception happened */
Packit Service a8c26c
int		type;	/* io type that was performed */
Packit Service a8c26c
ssize_t		io;	/* the io return value that indicated exception */
Packit Service a8c26c
Sfdisc_t*	disc;	/* discipline in use */
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg int		ev, local, lock;
Packit Service a8c26c
	reg ssize_t	size;
Packit Service a8c26c
	reg uchar*	data;
Packit Service a8c26c
	SFMTXDECL(f); /* declare a local stream variable for multithreading */
Packit Service a8c26c
Packit Service a8c26c
	SFMTXENTER(f,-1);
Packit Service a8c26c
Packit Service a8c26c
	GETLOCAL(f,local);
Packit Service a8c26c
	lock = f->mode&SF_LOCK;
Packit Service a8c26c
Packit Service a8c26c
	if(local && io <= 0)
Packit Service a8c26c
		f->flags |= io < 0 ? SF_ERROR : SF_EOF;
Packit Service a8c26c
Packit Service a8c26c
	if(disc && disc->exceptf)
Packit Service a8c26c
	{	/* let the stream be generally accessible for this duration */
Packit Service a8c26c
		if(local && lock)
Packit Service a8c26c
			SFOPEN(f,0);
Packit Service a8c26c
Packit Service a8c26c
		/* so that exception handler knows what we are asking for */
Packit Service a8c26c
		_Sfi = f->val = io;
Packit Service a8c26c
		ev = (*(disc->exceptf))(f,type,&io,disc);
Packit Service a8c26c
Packit Service a8c26c
		/* relock if necessary */
Packit Service a8c26c
		if(local && lock)
Packit Service a8c26c
			SFLOCK(f,0);
Packit Service a8c26c
Packit Service a8c26c
		if(io > 0 && !(f->flags&SF_STRING) )
Packit Service a8c26c
			SFMTXRETURN(f, ev);
Packit Service a8c26c
		if(ev < 0)
Packit Service a8c26c
			SFMTXRETURN(f, SF_EDONE);
Packit Service a8c26c
		if(ev > 0)
Packit Service a8c26c
			SFMTXRETURN(f, SF_EDISC);
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	if(f->flags&SF_STRING)
Packit Service a8c26c
	{	if(type == SF_READ)
Packit Service a8c26c
			goto chk_stack;
Packit Service a8c26c
		else if(type != SF_WRITE && type != SF_SEEK)
Packit Service a8c26c
			SFMTXRETURN(f, SF_EDONE);
Packit Service a8c26c
		if(local && io >= 0)
Packit Service a8c26c
		{	if(f->size >= 0 && !(f->flags&SF_MALLOC))
Packit Service a8c26c
				goto chk_stack;
Packit Service a8c26c
			/* extend buffer */
Packit Service a8c26c
			if((size = f->size) < 0)
Packit Service a8c26c
				size = 0;
Packit Service a8c26c
			if((io -= size) <= 0)
Packit Service a8c26c
				io = SF_GRAIN;
Packit Service a8c26c
			size = ((size+io+SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
Packit Service a8c26c
			if(f->size > 0)
Packit Service a8c26c
				data = (uchar*)realloc((char*)f->data,size);
Packit Service a8c26c
			else	data = (uchar*)malloc(size);
Packit Service a8c26c
			if(!data)
Packit Service a8c26c
				goto chk_stack;
Packit Service a8c26c
			f->endb = data + size;
Packit Service a8c26c
			f->next = data + (f->next - f->data);
Packit Service a8c26c
			f->endr = f->endw = f->data = data;
Packit Service a8c26c
			f->size = size;
Packit Service a8c26c
		}
Packit Service a8c26c
		SFMTXRETURN(f, SF_EDISC);
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	if(errno == EINTR)
Packit Service a8c26c
	{	if(_Sfexiting || (f->bits&SF_ENDING) ||	/* stop being a hero	*/
Packit Service a8c26c
		   (f->flags&SF_IOINTR) ) /* application requests to return	*/
Packit Service a8c26c
			SFMTXRETURN(f, SF_EDONE);
Packit Service a8c26c
Packit Service a8c26c
		/* a normal interrupt, we can continue */
Packit Service a8c26c
		errno = 0;
Packit Service a8c26c
		f->flags &= ~(SF_EOF|SF_ERROR);
Packit Service a8c26c
		SFMTXRETURN(f, SF_ECONT);
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
chk_stack:
Packit Service a8c26c
	if(local && f->push &&
Packit Service a8c26c
	   ((type == SF_READ  && f->next >= f->endb) ||
Packit Service a8c26c
	    (type == SF_WRITE && f->next <= f->data)))
Packit Service a8c26c
	{	/* pop the stack */
Packit Service a8c26c
		reg Sfio_t	*pf;
Packit Service a8c26c
Packit Service a8c26c
		if(lock)
Packit Service a8c26c
			SFOPEN(f,0);
Packit Service a8c26c
Packit Service a8c26c
		/* pop and close */
Packit Service a8c26c
		pf = (*_Sfstack)(f,NIL(Sfio_t*));
Packit Service a8c26c
		if((ev = sfclose(pf)) < 0) /* can't close, restack */
Packit Service a8c26c
			(*_Sfstack)(f,pf);
Packit Service a8c26c
Packit Service a8c26c
		if(lock)
Packit Service a8c26c
			SFLOCK(f,0);
Packit Service a8c26c
Packit Service a8c26c
		ev = ev < 0 ? SF_EDONE : SF_ESTACK;
Packit Service a8c26c
	}
Packit Service a8c26c
	else	ev = SF_EDONE;
Packit Service a8c26c
Packit Service a8c26c
	SFMTXRETURN(f, ev);
Packit Service a8c26c
}