xref: /titanic_50/usr/src/lib/libast/common/sfio/sfexcept.c (revision 23c57df72989c916b3e98084eb88d48777999691)
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 /*	Function to handle io exceptions.
25 **	Written by Kiem-Phong Vo
26 */
27 
28 #if __STD_C
29 int _sfexcept(Sfio_t* f, int type, ssize_t io, Sfdisc_t* disc)
30 #else
31 int _sfexcept(f,type,io,disc)
32 Sfio_t*		f;	/* stream where the exception happened */
33 int		type;	/* io type that was performed */
34 ssize_t		io;	/* the io return value that indicated exception */
35 Sfdisc_t*	disc;	/* discipline in use */
36 #endif
37 {
38 	reg int		ev, local, lock;
39 	reg ssize_t	size;
40 	reg uchar*	data;
41 
42 	SFMTXSTART(f,-1);
43 
44 	GETLOCAL(f,local);
45 	lock = f->mode&SF_LOCK;
46 
47 	if(local && io <= 0)
48 		f->flags |= io < 0 ? SF_ERROR : SF_EOF;
49 
50 	if(disc && disc->exceptf)
51 	{	/* let the stream be generally accessible for this duration */
52 		if(local && lock)
53 			SFOPEN(f,0);
54 
55 		/* so that exception handler knows what we are asking for */
56 		_Sfi = f->val = io;
57 		ev = (*(disc->exceptf))(f,type,&io,disc);
58 
59 		/* relock if necessary */
60 		if(local && lock)
61 			SFLOCK(f,0);
62 
63 		if(io > 0 && !(f->flags&SF_STRING) )
64 			SFMTXRETURN(f, ev);
65 		if(ev < 0)
66 			SFMTXRETURN(f, SF_EDONE);
67 		if(ev > 0)
68 			SFMTXRETURN(f, SF_EDISC);
69 	}
70 
71 	if(f->flags&SF_STRING)
72 	{	if(type == SF_READ)
73 			goto chk_stack;
74 		else if(type != SF_WRITE && type != SF_SEEK)
75 			SFMTXRETURN(f, SF_EDONE);
76 		if(local && io >= 0)
77 		{	if(f->size >= 0 && !(f->flags&SF_MALLOC))
78 				goto chk_stack;
79 			/* extend buffer */
80 			if((size = f->size) < 0)
81 				size = 0;
82 			if((io -= size) <= 0)
83 				io = SF_GRAIN;
84 			size = ((size+io+SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
85 			if(f->size > 0)
86 				data = (uchar*)realloc((char*)f->data,size);
87 			else	data = (uchar*)malloc(size);
88 			if(!data)
89 				goto chk_stack;
90 			f->endb = data + size;
91 			f->next = data + (f->next - f->data);
92 			f->endr = f->endw = f->data = data;
93 			f->size = size;
94 		}
95 		SFMTXRETURN(f, SF_EDISC);
96 	}
97 
98 	if(errno == EINTR)
99 	{	if(_Sfexiting || (f->bits&SF_ENDING) ||	/* stop being a hero	*/
100 		   (f->flags&SF_IOINTR) ) /* application requests to return	*/
101 			SFMTXRETURN(f, SF_EDONE);
102 
103 		/* a normal interrupt, we can continue */
104 		errno = 0;
105 		f->flags &= ~(SF_EOF|SF_ERROR);
106 		SFMTXRETURN(f, SF_ECONT);
107 	}
108 
109 chk_stack:
110 	if(local && f->push &&
111 	   ((type == SF_READ  && f->next >= f->endb) ||
112 	    (type == SF_WRITE && f->next <= f->data)))
113 	{	/* pop the stack */
114 		reg Sfio_t	*pf;
115 
116 		if(lock)
117 			SFOPEN(f,0);
118 
119 		/* pop and close */
120 		pf = (*_Sfstack)(f,NIL(Sfio_t*));
121 		if((ev = sfclose(pf)) < 0) /* can't close, restack */
122 			(*_Sfstack)(f,pf);
123 
124 		if(lock)
125 			SFLOCK(f,0);
126 
127 		ev = ev < 0 ? SF_EDONE : SF_ESTACK;
128 	}
129 	else	ev = SF_EDONE;
130 
131 	SFMTXRETURN(f, ev);
132 }
133