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