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 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