14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 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"
2310898Sroland.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.
4910898Sroland.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
_sfcleanup(void)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
_sfsetpool(Sfio_t * f)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
_sfrsrv(reg Sfio_t * f,reg ssize_t size)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
ignoresig(int sig)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
_sfpopen(reg Sfio_t * f,int fd,int pid,int stdio)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
_sfpclose(reg Sfio_t * f)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
_sfpmode(Sfio_t * f,int type)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
_sfmode(reg Sfio_t * f,reg int wanted,reg int local)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