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