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