14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1985-2009 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #include "sfhdr.h" 23*10898Sroland.mainz@nrubsig.org static char* Version = "\n@(#)$Id: sfio (AT&T Labs - Research) 2009-09-15 $\0\n"; 244887Schin 254887Schin /* Functions to set a given stream to some desired mode 264887Schin ** 274887Schin ** Written by Kiem-Phong Vo. 284887Schin ** 294887Schin ** Modifications: 304887Schin ** 06/27/1990 (first version) 314887Schin ** 01/06/1991 324887Schin ** 07/08/1991 334887Schin ** 06/18/1992 344887Schin ** 02/02/1993 354887Schin ** 05/25/1993 364887Schin ** 02/07/1994 374887Schin ** 05/21/1996 384887Schin ** 08/01/1997 394887Schin ** 08/01/1998 (extended formatting) 404887Schin ** 09/09/1999 (thread-safe) 414887Schin ** 02/01/2001 (adaptive buffering) 424887Schin ** 05/31/2002 (multi-byte handling in sfvprintf/vscanf) 434887Schin ** 09/06/2002 (SF_IOINTR flag) 444887Schin ** 11/15/2002 (%#c for sfvprintf) 454887Schin ** 05/31/2003 (sfsetbuf(f,f,align_size) to set alignment for data) 464887Schin ** (%I1d is fixed to handle "signed char" correctly) 474887Schin ** 01/01/2004 Porting issues to various platforms resolved. 488462SApril.Chin@Sun.COM ** 06/01/2008 Allowing notify() at entering/exiting thread-safe routines. 49*10898Sroland.mainz@nrubsig.org ** 09/15/2008 Add sfwalk(). 504887Schin */ 514887Schin 524887Schin /* the below is for protecting the application from SIGPIPE */ 534887Schin #if _PACKAGE_ast 544887Schin #include <sig.h> 554887Schin #include <wait.h> 564887Schin #define Sfsignal_f Sig_handler_t 574887Schin #else 584887Schin #include <signal.h> 594887Schin typedef void(* Sfsignal_f)_ARG_((int)); 604887Schin #endif 614887Schin static int _Sfsigp = 0; /* # of streams needing SIGPIPE protection */ 624887Schin 634887Schin /* done at exiting time */ 644887Schin #if __STD_C 654887Schin static void _sfcleanup(void) 664887Schin #else 674887Schin static void _sfcleanup() 684887Schin #endif 694887Schin { 704887Schin reg Sfpool_t* p; 714887Schin reg Sfio_t* f; 724887Schin reg int n; 734887Schin reg int pool; 744887Schin 754887Schin f = (Sfio_t*)Version; /* shut compiler warning */ 764887Schin 774887Schin /* set this so that no more buffering is allowed for write streams */ 784887Schin _Sfexiting = 1001; 794887Schin 804887Schin sfsync(NIL(Sfio_t*)); 814887Schin 824887Schin for(p = &_Sfpool; p; p = p->next) 834887Schin { for(n = 0; n < p->n_sf; ++n) 844887Schin { if(!(f = p->sf[n]) || SFFROZEN(f) ) 854887Schin continue; 864887Schin 874887Schin SFLOCK(f,0); 884887Schin SFMTXLOCK(f); 894887Schin 904887Schin /* let application know that we are leaving */ 914887Schin (void)SFRAISE(f, SF_ATEXIT, NIL(Void_t*)); 924887Schin 934887Schin if(f->flags&SF_STRING) 944887Schin continue; 954887Schin 964887Schin /* from now on, write streams are unbuffered */ 974887Schin pool = f->mode&SF_POOL; 984887Schin f->mode &= ~SF_POOL; 994887Schin if((f->flags&SF_WRITE) && !(f->mode&SF_WRITE)) 1004887Schin (void)_sfmode(f,SF_WRITE,1); 1014887Schin if(((f->bits&SF_MMAP) && f->data) || 1024887Schin ((f->mode&SF_WRITE) && f->next == f->data) ) 1034887Schin (void)SFSETBUF(f,NIL(Void_t*),0); 1044887Schin f->mode |= pool; 1054887Schin 1064887Schin SFMTXUNLOCK(f); 1074887Schin SFOPEN(f,0); 1084887Schin } 1094887Schin } 1104887Schin } 1114887Schin 1124887Schin /* put into discrete pool */ 1134887Schin #if __STD_C 1144887Schin int _sfsetpool(Sfio_t* f) 1154887Schin #else 1164887Schin int _sfsetpool(f) 1174887Schin Sfio_t* f; 1184887Schin #endif 1194887Schin { 1204887Schin reg Sfpool_t* p; 1214887Schin reg Sfio_t** array; 1224887Schin reg int n, rv; 1234887Schin 1244887Schin if(!_Sfcleanup) 1254887Schin { _Sfcleanup = _sfcleanup; 1264887Schin (void)atexit(_sfcleanup); 1274887Schin } 1284887Schin 1294887Schin if(!(p = f->pool) ) 1304887Schin p = f->pool = &_Sfpool; 1314887Schin 1328462SApril.Chin@Sun.COM POOLMTXENTER(p); 1334887Schin 1344887Schin rv = -1; 1354887Schin 1364887Schin if(p->n_sf >= p->s_sf) 1374887Schin { if(p->s_sf == 0) /* initialize pool array */ 1384887Schin { p->s_sf = sizeof(p->array)/sizeof(p->array[0]); 1394887Schin p->sf = p->array; 1404887Schin } 1414887Schin else /* allocate a larger array */ 1424887Schin { n = (p->sf != p->array ? p->s_sf : (p->s_sf/4 + 1)*4) + 4; 1434887Schin if(!(array = (Sfio_t**)malloc(n*sizeof(Sfio_t*))) ) 1444887Schin goto done; 1454887Schin 1464887Schin /* move old array to new one */ 1474887Schin memcpy((Void_t*)array,(Void_t*)p->sf,p->n_sf*sizeof(Sfio_t*)); 1484887Schin if(p->sf != p->array) 1494887Schin free((Void_t*)p->sf); 1504887Schin 1514887Schin p->sf = array; 1524887Schin p->s_sf = n; 1534887Schin } 1544887Schin } 1554887Schin 1564887Schin /* always add at end of array because if this was done during some sort 1574887Schin of walk thru all streams, we'll want the new stream to be seen. 1584887Schin */ 1594887Schin p->sf[p->n_sf++] = f; 1604887Schin rv = 0; 1614887Schin 1624887Schin done: 1634887Schin POOLMTXRETURN(p, rv); 1644887Schin } 1654887Schin 1664887Schin /* create an auxiliary buffer for sfgetr/sfreserve/sfputr */ 1674887Schin #if __STD_C 1684887Schin Sfrsrv_t* _sfrsrv(reg Sfio_t* f, reg ssize_t size) 1694887Schin #else 1704887Schin Sfrsrv_t* _sfrsrv(f,size) 1714887Schin reg Sfio_t* f; 1724887Schin reg ssize_t size; 1734887Schin #endif 1744887Schin { 1754887Schin Sfrsrv_t *rsrv, *rs; 1764887Schin 1774887Schin /* make buffer if nothing yet */ 1784887Schin size = ((size + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN; 1794887Schin if(!(rsrv = f->rsrv) || size > rsrv->size) 1804887Schin { if(!(rs = (Sfrsrv_t*)malloc(size+sizeof(Sfrsrv_t)))) 1814887Schin size = -1; 1824887Schin else 1834887Schin { if(rsrv) 1844887Schin { if(rsrv->slen > 0) 1854887Schin memcpy(rs,rsrv,sizeof(Sfrsrv_t)+rsrv->slen); 1864887Schin free(rsrv); 1874887Schin } 1884887Schin f->rsrv = rsrv = rs; 1894887Schin rsrv->size = size; 1904887Schin rsrv->slen = 0; 1914887Schin } 1924887Schin } 1934887Schin 1944887Schin if(rsrv && size > 0) 1954887Schin rsrv->slen = 0; 1964887Schin 1974887Schin return size >= 0 ? rsrv : NIL(Sfrsrv_t*); 1984887Schin } 1994887Schin 2004887Schin #ifdef SIGPIPE 2014887Schin #if __STD_C 2024887Schin static void ignoresig(int sig) 2034887Schin #else 2044887Schin static void ignoresig(sig) 2054887Schin int sig; 2064887Schin #endif 2074887Schin { 2084887Schin signal(sig, ignoresig); 2094887Schin } 2104887Schin #endif 2114887Schin 2124887Schin #if __STD_C 2134887Schin int _sfpopen(reg Sfio_t* f, int fd, int pid, int stdio) 2144887Schin #else 2154887Schin int _sfpopen(f, fd, pid, stdio) 2164887Schin reg Sfio_t* f; 2174887Schin int fd; 2184887Schin int pid; 2194887Schin int stdio; /* stdio popen() does not reset SIGPIPE handler */ 2204887Schin #endif 2214887Schin { 2224887Schin reg Sfproc_t* p; 2234887Schin 2244887Schin if(f->proc) 2254887Schin return 0; 2264887Schin 2274887Schin if(!(p = f->proc = (Sfproc_t*)malloc(sizeof(Sfproc_t))) ) 2284887Schin return -1; 2294887Schin 2304887Schin p->pid = pid; 2314887Schin p->size = p->ndata = 0; 2324887Schin p->rdata = NIL(uchar*); 2334887Schin p->file = fd; 2344887Schin p->sigp = (!stdio && pid >= 0 && (f->flags&SF_WRITE)) ? 1 : 0; 2354887Schin 2364887Schin #ifdef SIGPIPE /* protect from broken pipe signal */ 2374887Schin if(p->sigp) 2384887Schin { Sfsignal_f handler; 2394887Schin 2404887Schin (void)vtmtxlock(_Sfmutex); 2414887Schin if((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL && 2424887Schin handler != ignoresig) 2434887Schin signal(SIGPIPE, handler); /* honor user handler */ 2444887Schin _Sfsigp += 1; 2454887Schin (void)vtmtxunlock(_Sfmutex); 2464887Schin } 2474887Schin #endif 2484887Schin 2494887Schin return 0; 2504887Schin } 2514887Schin 2524887Schin #if __STD_C 2534887Schin int _sfpclose(reg Sfio_t* f) 2544887Schin #else 2554887Schin int _sfpclose(f) 2564887Schin reg Sfio_t* f; /* stream to close */ 2574887Schin #endif 2584887Schin { 2594887Schin Sfproc_t* p; 2604887Schin int pid, status; 2614887Schin 2624887Schin if(!(p = f->proc)) 2634887Schin return -1; 2644887Schin f->proc = NIL(Sfproc_t*); 2654887Schin 2664887Schin if(p->rdata) 2674887Schin free(p->rdata); 2684887Schin 2694887Schin if(p->pid < 0) 2704887Schin status = 0; 2714887Schin else 2724887Schin { /* close the associated stream */ 2734887Schin if(p->file >= 0) 2744887Schin CLOSE(p->file); 2754887Schin 2764887Schin /* wait for process termination */ 2774887Schin #if _PACKAGE_ast 2784887Schin sigcritical(SIG_REG_EXEC|SIG_REG_PROC); 2794887Schin #endif 2804887Schin while ((pid = waitpid(p->pid,&status,0)) == -1 && errno == EINTR) 2814887Schin ; 2824887Schin if(pid == -1) 2834887Schin status = -1; 2844887Schin #if _PACKAGE_ast 2854887Schin sigcritical(0); 2864887Schin #endif 2874887Schin 2884887Schin #ifdef SIGPIPE 2894887Schin (void)vtmtxlock(_Sfmutex); 2904887Schin if(p->sigp && (_Sfsigp -= 1) <= 0) 2914887Schin { Sfsignal_f handler; 2924887Schin if((handler = signal(SIGPIPE,SIG_DFL)) != SIG_DFL && 2934887Schin handler != ignoresig) 2944887Schin signal(SIGPIPE,handler); /* honor user handler */ 2954887Schin _Sfsigp = 0; 2964887Schin } 2974887Schin (void)vtmtxunlock(_Sfmutex); 2984887Schin #endif 2994887Schin } 3004887Schin 3014887Schin free(p); 3024887Schin return status; 3034887Schin } 3044887Schin 3054887Schin #if __STD_C 3064887Schin static int _sfpmode(Sfio_t* f, int type) 3074887Schin #else 3084887Schin static int _sfpmode(f,type) 3094887Schin Sfio_t* f; 3104887Schin int type; 3114887Schin #endif 3124887Schin { 3134887Schin Sfproc_t* p; 3144887Schin 3154887Schin if(!(p = f->proc) ) 3164887Schin return -1; 3174887Schin 3184887Schin if(type == SF_WRITE) 3194887Schin { /* save unread data */ 3204887Schin p->ndata = f->endb-f->next; 3214887Schin if(p->ndata > p->size) 3224887Schin { if(p->rdata) 3234887Schin free((char*)p->rdata); 3244887Schin if((p->rdata = (uchar*)malloc(p->ndata)) ) 3254887Schin p->size = p->ndata; 3264887Schin else 3274887Schin { p->size = 0; 3284887Schin return -1; 3294887Schin } 3304887Schin } 3314887Schin if(p->ndata > 0) 3324887Schin memcpy((Void_t*)p->rdata,(Void_t*)f->next,p->ndata); 3334887Schin f->endb = f->data; 3344887Schin } 3354887Schin else 3364887Schin { /* restore read data */ 3374887Schin if(p->ndata > f->size) /* may lose data!!! */ 3384887Schin p->ndata = f->size; 3394887Schin if(p->ndata > 0) 3404887Schin { memcpy((Void_t*)f->data,(Void_t*)p->rdata,p->ndata); 3414887Schin f->endb = f->data+p->ndata; 3424887Schin p->ndata = 0; 3434887Schin } 3444887Schin } 3454887Schin 3464887Schin /* switch file descriptor */ 3474887Schin if(p->pid >= 0) 3484887Schin { type = f->file; 3494887Schin f->file = p->file; 3504887Schin p->file = type; 3514887Schin } 3524887Schin 3534887Schin return 0; 3544887Schin } 3554887Schin 3564887Schin #if __STD_C 3574887Schin int _sfmode(reg Sfio_t* f, reg int wanted, reg int local) 3584887Schin #else 3594887Schin int _sfmode(f, wanted, local) 3604887Schin reg Sfio_t* f; /* change r/w mode and sync file pointer for this stream */ 3614887Schin reg int wanted; /* desired mode */ 3624887Schin reg int local; /* a local call */ 3634887Schin #endif 3644887Schin { 3654887Schin reg int n; 3664887Schin Sfoff_t addr; 3674887Schin reg int rv = 0; 3684887Schin 3694887Schin SFONCE(); /* initialize mutexes */ 3704887Schin 3714887Schin if(wanted&SF_SYNCED) /* for (SF_SYNCED|SF_READ) stream, just junk data */ 3724887Schin { wanted &= ~SF_SYNCED; 3734887Schin if((f->mode&(SF_SYNCED|SF_READ)) == (SF_SYNCED|SF_READ) ) 3744887Schin { f->next = f->endb = f->endr = f->data; 3754887Schin f->mode &= ~SF_SYNCED; 3764887Schin } 3774887Schin } 3784887Schin 3794887Schin if((!local && SFFROZEN(f)) || (!(f->flags&SF_STRING) && f->file < 0)) 3804887Schin { if(local || !f->disc || !f->disc->exceptf) 3814887Schin { local = 1; 3824887Schin goto err_notify; 3834887Schin } 3844887Schin 3854887Schin for(;;) 3864887Schin { if((rv = (*f->disc->exceptf)(f,SF_LOCKED,0,f->disc)) < 0) 3874887Schin return rv; 3884887Schin if((!local && SFFROZEN(f)) || 3894887Schin (!(f->flags&SF_STRING) && f->file < 0) ) 3904887Schin { if(rv == 0) 3914887Schin { local = 1; 3924887Schin goto err_notify; 3934887Schin } 3944887Schin else continue; 3954887Schin } 3964887Schin else break; 3974887Schin } 3984887Schin } 3994887Schin 4004887Schin if(f->mode&SF_GETR) 4014887Schin { f->mode &= ~SF_GETR; 4024887Schin #ifdef MAP_TYPE 4034887Schin if((f->bits&SF_MMAP) && (f->tiny[0] += 1) >= (4*SF_NMAP) ) 4044887Schin { /* turn off mmap to avoid page faulting */ 4054887Schin sfsetbuf(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND); 4064887Schin f->tiny[0] = 0; 4074887Schin } 4084887Schin else 4094887Schin #endif 4104887Schin if(f->getr) 4114887Schin { f->next[-1] = f->getr; 4124887Schin f->getr = 0; 4134887Schin } 4144887Schin } 4154887Schin 4164887Schin if(f->mode&SF_STDIO) /* synchronizing with stdio pointers */ 4174887Schin (*_Sfstdsync)(f); 4184887Schin 4194887Schin if(f->disc == _Sfudisc && wanted == SF_WRITE && 4204887Schin sfclose((*_Sfstack)(f,NIL(Sfio_t*))) < 0 ) 4214887Schin { local = 1; 4224887Schin goto err_notify; 4234887Schin } 4244887Schin 4254887Schin if(f->mode&SF_POOL) 4264887Schin { /* move to head of pool */ 4274887Schin if(f == f->pool->sf[0] || (*_Sfpmove)(f,0) < 0 ) 4284887Schin { local = 1; 4294887Schin goto err_notify; 4304887Schin } 4314887Schin f->mode &= ~SF_POOL; 4324887Schin } 4334887Schin 4344887Schin SFLOCK(f,local); 4354887Schin 4364887Schin /* buffer initialization */ 4374887Schin wanted &= SF_RDWR; 4384887Schin if(f->mode&SF_INIT) 4394887Schin { 4404887Schin if(!f->pool && _sfsetpool(f) < 0) 4414887Schin { rv = -1; 4424887Schin goto done; 4434887Schin } 4444887Schin 4454887Schin if(wanted == 0) 4464887Schin goto done; 4474887Schin 4484887Schin if(wanted != (int)(f->mode&SF_RDWR) && !(f->flags&wanted) ) 4494887Schin goto err_notify; 4504887Schin 4514887Schin if((f->flags&SF_STRING) && f->size >= 0 && f->data) 4524887Schin { f->mode &= ~SF_INIT; 4534887Schin f->extent = ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ? 4544887Schin f->size : 0; 4554887Schin f->here = 0; 4564887Schin f->endb = f->data + f->size; 4574887Schin f->next = f->endr = f->endw = f->data; 4584887Schin if(f->mode&SF_READ) 4594887Schin f->endr = f->endb; 4604887Schin else f->endw = f->endb; 4614887Schin } 4624887Schin else 4634887Schin { n = f->flags; 4644887Schin (void)SFSETBUF(f,f->data,f->size); 4654887Schin f->flags |= (n&SF_MALLOC); 4664887Schin } 4674887Schin } 4684887Schin 4694887Schin if(wanted == (int)SFMODE(f,1)) 4704887Schin goto done; 4714887Schin 4724887Schin switch(SFMODE(f,1)) 4734887Schin { 4744887Schin case SF_WRITE: /* switching to SF_READ */ 4754887Schin if(wanted == 0 || wanted == SF_WRITE) 4764887Schin break; 4774887Schin if(!(f->flags&SF_READ) ) 4784887Schin goto err_notify; 4794887Schin else if(f->flags&SF_STRING) 4804887Schin { SFSTRSIZE(f); 4814887Schin f->endb = f->data+f->extent; 4824887Schin f->mode = SF_READ; 4834887Schin break; 4844887Schin } 4854887Schin 4864887Schin /* reset buffer */ 4874887Schin if(f->next > f->data && SFFLSBUF(f,-1) < 0) 4884887Schin goto err_notify; 4894887Schin 4904887Schin if(f->size == 0) 4914887Schin { /* unbuffered */ 4924887Schin f->data = f->tiny; 4934887Schin f->size = sizeof(f->tiny); 4944887Schin } 4954887Schin f->next = f->endr = f->endw = f->endb = f->data; 4964887Schin f->mode = SF_READ|SF_LOCK; 4974887Schin 4984887Schin /* restore saved read data for coprocess */ 4994887Schin if(f->proc && _sfpmode(f,wanted) < 0) 5004887Schin goto err_notify; 5014887Schin 5024887Schin break; 5034887Schin 5044887Schin case (SF_READ|SF_SYNCED): /* a previously sync-ed read stream */ 5054887Schin if(wanted != SF_WRITE) 5064887Schin { /* just reset the pointers */ 5074887Schin f->mode = SF_READ|SF_LOCK; 5084887Schin 5094887Schin /* see if must go with new physical location */ 5104887Schin if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC) && 5114887Schin (addr = SFSK(f,0,SEEK_CUR,f->disc)) != f->here) 5124887Schin { 5134887Schin #ifdef MAP_TYPE 5144887Schin if((f->bits&SF_MMAP) && f->data) 5154887Schin { SFMUNMAP(f,f->data,f->endb-f->data); 5164887Schin f->data = NIL(uchar*); 5174887Schin } 5184887Schin #endif 5194887Schin f->endb = f->endr = f->endw = f->next = f->data; 5204887Schin f->here = addr; 5214887Schin } 5224887Schin else 5234887Schin { addr = f->here + (f->endb - f->next); 5244887Schin if(SFSK(f,addr,SEEK_SET,f->disc) < 0) 5254887Schin goto err_notify; 5264887Schin f->here = addr; 5274887Schin } 5284887Schin 5294887Schin break; 5304887Schin } 5314887Schin /* fall thru */ 5324887Schin 5334887Schin case SF_READ: /* switching to SF_WRITE */ 5344887Schin if(wanted != SF_WRITE) 5354887Schin break; 5364887Schin else if(!(f->flags&SF_WRITE)) 5374887Schin goto err_notify; 5384887Schin else if(f->flags&SF_STRING) 5394887Schin { f->endb = f->data+f->size; 5404887Schin f->mode = SF_WRITE|SF_LOCK; 5414887Schin break; 5424887Schin } 5434887Schin 5444887Schin /* save unread data before switching mode */ 5454887Schin if(f->proc && _sfpmode(f,wanted) < 0) 5464887Schin goto err_notify; 5474887Schin 5484887Schin /* reset buffer and seek pointer */ 5494887Schin if(!(f->mode&SF_SYNCED) ) 5504887Schin { n = f->endb - f->next; 5514887Schin if(f->extent >= 0 && (n > 0 || (f->data && (f->bits&SF_MMAP))) ) 5524887Schin { /* reset file pointer */ 5534887Schin addr = f->here - n; 5544887Schin if(SFSK(f,addr,SEEK_SET,f->disc) < 0) 5554887Schin goto err_notify; 5564887Schin f->here = addr; 5574887Schin } 5584887Schin } 5594887Schin 5604887Schin f->mode = SF_WRITE|SF_LOCK; 5614887Schin #ifdef MAP_TYPE 5624887Schin if(f->bits&SF_MMAP) 5634887Schin { if(f->data) 5644887Schin SFMUNMAP(f,f->data,f->endb-f->data); 5654887Schin (void)SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND); 5664887Schin } 5674887Schin #endif 5684887Schin if(f->data == f->tiny) 5694887Schin { f->endb = f->data = f->next = NIL(uchar*); 5704887Schin f->size = 0; 5714887Schin } 5724887Schin else f->endb = (f->next = f->data) + f->size; 5734887Schin 5744887Schin break; 5754887Schin 5764887Schin default: /* unknown case */ 5774887Schin err_notify: 5784887Schin if((wanted &= SF_RDWR) == 0 && (wanted = f->flags&SF_RDWR) == SF_RDWR) 5794887Schin wanted = SF_READ; 5804887Schin 5814887Schin /* set errno for operations that access wrong stream type */ 5824887Schin if(wanted != (f->mode&SF_RDWR) && f->file >= 0) 5834887Schin errno = EBADF; 5844887Schin 5854887Schin if(_Sfnotify) /* notify application of the error */ 5868462SApril.Chin@Sun.COM (*_Sfnotify)(f, wanted, (void*)((long)f->file)); 5874887Schin 5884887Schin rv = -1; 5894887Schin break; 5904887Schin } 5914887Schin 5924887Schin done: 5934887Schin SFOPEN(f,local); 5944887Schin return rv; 5954887Schin } 596