1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
24 /* Function to handle io exceptions.
25 ** Written by Kiem-Phong Vo
29 int _sfexcept(Sfio_t
* f
, int type
, ssize_t io
, Sfdisc_t
* disc
)
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 */
38 reg
int ev
, local
, lock
;
46 lock
= f
->mode
&SF_LOCK
;
49 f
->flags
|= io
< 0 ? SF_ERROR
: SF_EOF
;
51 if(disc
&& disc
->exceptf
)
52 { /* let the stream be generally accessible for this duration */
56 /* so that exception handler knows what we are asking for */
58 ev
= (*(disc
->exceptf
))(f
,type
,&io
,disc
);
60 /* relock if necessary */
64 if(io
> 0 && !(f
->flags
&SF_STRING
) )
67 SFMTXRETURN(f
, SF_EDONE
);
69 SFMTXRETURN(f
, SF_EDISC
);
72 if(f
->flags
&SF_STRING
)
75 else if(type
!= SF_WRITE
&& type
!= SF_SEEK
)
76 SFMTXRETURN(f
, SF_EDONE
);
78 { if(f
->size
>= 0 && !(f
->flags
&SF_MALLOC
))
81 if((size
= f
->size
) < 0)
85 size
= ((size
+io
+SF_GRAIN
-1)/SF_GRAIN
)*SF_GRAIN
;
87 data
= (uchar
*)realloc((char*)f
->data
,size
);
88 else data
= (uchar
*)malloc(size
);
91 f
->endb
= data
+ size
;
92 f
->next
= data
+ (f
->next
- f
->data
);
93 f
->endr
= f
->endw
= f
->data
= data
;
96 SFMTXRETURN(f
, SF_EDISC
);
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
);
104 /* a normal interrupt, we can continue */
106 f
->flags
&= ~(SF_EOF
|SF_ERROR
);
107 SFMTXRETURN(f
, SF_ECONT
);
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 */
121 pf
= (*_Sfstack
)(f
,NIL(Sfio_t
*));
122 if((ev
= sfclose(pf
)) < 0) /* can't close, restack */
128 ev
= ev
< 0 ? SF_EDONE
: SF_ESTACK
;