1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #include "sfhdr.h"
23da2e3ebdSchin
24da2e3ebdSchin /* Function to handle io exceptions.
25da2e3ebdSchin ** Written by Kiem-Phong Vo
26da2e3ebdSchin */
27da2e3ebdSchin
28da2e3ebdSchin #if __STD_C
_sfexcept(Sfio_t * f,int type,ssize_t io,Sfdisc_t * disc)29da2e3ebdSchin int _sfexcept(Sfio_t* f, int type, ssize_t io, Sfdisc_t* disc)
30da2e3ebdSchin #else
31da2e3ebdSchin int _sfexcept(f,type,io,disc)
32da2e3ebdSchin Sfio_t* f; /* stream where the exception happened */
33da2e3ebdSchin int type; /* io type that was performed */
34da2e3ebdSchin ssize_t io; /* the io return value that indicated exception */
35da2e3ebdSchin Sfdisc_t* disc; /* discipline in use */
36da2e3ebdSchin #endif
37da2e3ebdSchin {
38da2e3ebdSchin reg int ev, local, lock;
39da2e3ebdSchin reg ssize_t size;
40da2e3ebdSchin reg uchar* data;
417c2fbfb3SApril Chin SFMTXDECL(f);
42da2e3ebdSchin
437c2fbfb3SApril Chin SFMTXENTER(f,-1);
44da2e3ebdSchin
45da2e3ebdSchin GETLOCAL(f,local);
46da2e3ebdSchin lock = f->mode&SF_LOCK;
47da2e3ebdSchin
48da2e3ebdSchin if(local && io <= 0)
49da2e3ebdSchin f->flags |= io < 0 ? SF_ERROR : SF_EOF;
50da2e3ebdSchin
51da2e3ebdSchin if(disc && disc->exceptf)
52da2e3ebdSchin { /* let the stream be generally accessible for this duration */
53da2e3ebdSchin if(local && lock)
54da2e3ebdSchin SFOPEN(f,0);
55da2e3ebdSchin
56da2e3ebdSchin /* so that exception handler knows what we are asking for */
57da2e3ebdSchin _Sfi = f->val = io;
58da2e3ebdSchin ev = (*(disc->exceptf))(f,type,&io,disc);
59da2e3ebdSchin
60da2e3ebdSchin /* relock if necessary */
61da2e3ebdSchin if(local && lock)
62da2e3ebdSchin SFLOCK(f,0);
63da2e3ebdSchin
64da2e3ebdSchin if(io > 0 && !(f->flags&SF_STRING) )
65da2e3ebdSchin SFMTXRETURN(f, ev);
66da2e3ebdSchin if(ev < 0)
67da2e3ebdSchin SFMTXRETURN(f, SF_EDONE);
68da2e3ebdSchin if(ev > 0)
69da2e3ebdSchin SFMTXRETURN(f, SF_EDISC);
70da2e3ebdSchin }
71da2e3ebdSchin
72da2e3ebdSchin if(f->flags&SF_STRING)
73da2e3ebdSchin { if(type == SF_READ)
74da2e3ebdSchin goto chk_stack;
75da2e3ebdSchin else if(type != SF_WRITE && type != SF_SEEK)
76da2e3ebdSchin SFMTXRETURN(f, SF_EDONE);
77da2e3ebdSchin if(local && io >= 0)
78da2e3ebdSchin { if(f->size >= 0 && !(f->flags&SF_MALLOC))
79da2e3ebdSchin goto chk_stack;
80da2e3ebdSchin /* extend buffer */
81da2e3ebdSchin if((size = f->size) < 0)
82da2e3ebdSchin size = 0;
83da2e3ebdSchin if((io -= size) <= 0)
84da2e3ebdSchin io = SF_GRAIN;
85da2e3ebdSchin size = ((size+io+SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
86da2e3ebdSchin if(f->size > 0)
87da2e3ebdSchin data = (uchar*)realloc((char*)f->data,size);
88da2e3ebdSchin else data = (uchar*)malloc(size);
89da2e3ebdSchin if(!data)
90da2e3ebdSchin goto chk_stack;
91da2e3ebdSchin f->endb = data + size;
92da2e3ebdSchin f->next = data + (f->next - f->data);
93da2e3ebdSchin f->endr = f->endw = f->data = data;
94da2e3ebdSchin f->size = size;
95da2e3ebdSchin }
96da2e3ebdSchin SFMTXRETURN(f, SF_EDISC);
97da2e3ebdSchin }
98da2e3ebdSchin
99da2e3ebdSchin if(errno == EINTR)
100da2e3ebdSchin { if(_Sfexiting || (f->bits&SF_ENDING) || /* stop being a hero */
101da2e3ebdSchin (f->flags&SF_IOINTR) ) /* application requests to return */
102da2e3ebdSchin SFMTXRETURN(f, SF_EDONE);
103da2e3ebdSchin
104da2e3ebdSchin /* a normal interrupt, we can continue */
105da2e3ebdSchin errno = 0;
106da2e3ebdSchin f->flags &= ~(SF_EOF|SF_ERROR);
107da2e3ebdSchin SFMTXRETURN(f, SF_ECONT);
108da2e3ebdSchin }
109da2e3ebdSchin
110da2e3ebdSchin chk_stack:
111da2e3ebdSchin if(local && f->push &&
112da2e3ebdSchin ((type == SF_READ && f->next >= f->endb) ||
113da2e3ebdSchin (type == SF_WRITE && f->next <= f->data)))
114da2e3ebdSchin { /* pop the stack */
115da2e3ebdSchin reg Sfio_t *pf;
116da2e3ebdSchin
117da2e3ebdSchin if(lock)
118da2e3ebdSchin SFOPEN(f,0);
119da2e3ebdSchin
120da2e3ebdSchin /* pop and close */
121da2e3ebdSchin pf = (*_Sfstack)(f,NIL(Sfio_t*));
122da2e3ebdSchin if((ev = sfclose(pf)) < 0) /* can't close, restack */
123da2e3ebdSchin (*_Sfstack)(f,pf);
124da2e3ebdSchin
125da2e3ebdSchin if(lock)
126da2e3ebdSchin SFLOCK(f,0);
127da2e3ebdSchin
128da2e3ebdSchin ev = ev < 0 ? SF_EDONE : SF_ESTACK;
129da2e3ebdSchin }
130da2e3ebdSchin else ev = SF_EDONE;
131da2e3ebdSchin
132da2e3ebdSchin SFMTXRETURN(f, ev);
133da2e3ebdSchin }
134