da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "sfhdr.h"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzstatic char* Version = "\n@(#)$Id: sfio (AT&T Labs - Research) 2009-09-15 $\0\n";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Functions to set a given stream to some desired mode
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Modifications:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 06/27/1990 (first version)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 01/06/1991
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 07/08/1991
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 06/18/1992
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 02/02/1993
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 05/25/1993
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 02/07/1994
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 05/21/1996
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 08/01/1997
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 08/01/1998 (extended formatting)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 09/09/1999 (thread-safe)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 02/01/2001 (adaptive buffering)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 05/31/2002 (multi-byte handling in sfvprintf/vscanf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 09/06/2002 (SF_IOINTR flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 11/15/2002 (%#c for sfvprintf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 05/31/2003 (sfsetbuf(f,f,align_size) to set alignment for data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** (%I1d is fixed to handle "signed char" correctly)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** 01/01/2004 Porting issues to various platforms resolved.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin** 06/01/2008 Allowing notify() at entering/exiting thread-safe routines.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz** 09/15/2008 Add sfwalk().
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* the below is for protecting the application from SIGPIPE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _PACKAGE_ast
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <sig.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <wait.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define Sfsignal_f Sig_handler_t
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <signal.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef void(* Sfsignal_f)_ARG_((int));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int _Sfsigp = 0; /* # of streams needing SIGPIPE protection */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* done at exiting time */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void _sfcleanup(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void _sfcleanup()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Sfpool_t* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Sfio_t* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int pool;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = (Sfio_t*)Version; /* shut compiler warning */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set this so that no more buffering is allowed for write streams */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Sfexiting = 1001;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(NIL(Sfio_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(p = &_Sfpool; p; p = p->next)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { for(n = 0; n < p->n_sf; ++n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(!(f = p->sf[n]) || SFFROZEN(f) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXLOCK(f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* let application know that we are leaving */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFRAISE(f, SF_ATEXIT, NIL(Void_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->flags&SF_STRING)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* from now on, write streams are unbuffered */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pool = f->mode&SF_POOL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode &= ~SF_POOL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->flags&SF_WRITE) && !(f->mode&SF_WRITE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)_sfmode(f,SF_WRITE,1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(((f->bits&SF_MMAP) && f->data) ||
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((f->mode&SF_WRITE) && f->next == f->data) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFSETBUF(f,NIL(Void_t*),0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode |= pool;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXUNLOCK(f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFOPEN(f,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* put into discrete pool */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint _sfsetpool(Sfio_t* f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint _sfsetpool(f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Sfpool_t* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Sfio_t** array;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int n, rv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!_Sfcleanup)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { _Sfcleanup = _sfcleanup;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)atexit(_sfcleanup);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(p = f->pool) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p = f->pool = &_Sfpool;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin POOLMTXENTER(p);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->n_sf >= p->s_sf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(p->s_sf == 0) /* initialize pool array */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { p->s_sf = sizeof(p->array)/sizeof(p->array[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->sf = p->array;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* allocate a larger array */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { n = (p->sf != p->array ? p->s_sf : (p->s_sf/4 + 1)*4) + 4;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(array = (Sfio_t**)malloc(n*sizeof(Sfio_t*))) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* move old array to new one */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy((Void_t*)array,(Void_t*)p->sf,p->n_sf*sizeof(Sfio_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->sf != p->array)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free((Void_t*)p->sf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->sf = array;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->s_sf = n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* always add at end of array because if this was done during some sort
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin of walk thru all streams, we'll want the new stream to be seen.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->sf[p->n_sf++] = f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chindone:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin POOLMTXRETURN(p, rv);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* create an auxiliary buffer for sfgetr/sfreserve/sfputr */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfrsrv_t* _sfrsrv(reg Sfio_t* f, reg ssize_t size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfrsrv_t* _sfrsrv(f,size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg Sfio_t* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg ssize_t size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfrsrv_t *rsrv, *rs;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make buffer if nothing yet */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = ((size + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(rsrv = f->rsrv) || size > rsrv->size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(!(rs = (Sfrsrv_t*)malloc(size+sizeof(Sfrsrv_t))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(rsrv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(rsrv->slen > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy(rs,rsrv,sizeof(Sfrsrv_t)+rsrv->slen);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(rsrv);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->rsrv = rsrv = rs;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rsrv->size = size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rsrv->slen = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rsrv && size > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rsrv->slen = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return size >= 0 ? rsrv : NIL(Sfrsrv_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGPIPE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void ignoresig(int sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void ignoresig(sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint sig;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(sig, ignoresig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint _sfpopen(reg Sfio_t* f, int fd, int pid, int stdio)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint _sfpopen(f, fd, pid, stdio)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg Sfio_t* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint fd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint stdio; /* stdio popen() does not reset SIGPIPE handler */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Sfproc_t* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->proc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(p = f->proc = (Sfproc_t*)malloc(sizeof(Sfproc_t))) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->pid = pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->size = p->ndata = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->rdata = NIL(uchar*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->file = fd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->sigp = (!stdio && pid >= 0 && (f->flags&SF_WRITE)) ? 1 : 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGPIPE /* protect from broken pipe signal */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->sigp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { Sfsignal_f handler;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)vtmtxlock(_Sfmutex);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin handler != ignoresig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(SIGPIPE, handler); /* honor user handler */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Sfsigp += 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)vtmtxunlock(_Sfmutex);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint _sfpclose(reg Sfio_t* f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint _sfpclose(f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg Sfio_t* f; /* stream to close */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfproc_t* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int pid, status;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(p = f->proc))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->proc = NIL(Sfproc_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->rdata)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(p->rdata);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->pid < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin status = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* close the associated stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->file >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin CLOSE(p->file);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* wait for process termination */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _PACKAGE_ast
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigcritical(SIG_REG_EXEC|SIG_REG_PROC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while ((pid = waitpid(p->pid,&status,0)) == -1 && errno == EINTR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid == -1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin status = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _PACKAGE_ast
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigcritical(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGPIPE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)vtmtxlock(_Sfmutex);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->sigp && (_Sfsigp -= 1) <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { Sfsignal_f handler;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((handler = signal(SIGPIPE,SIG_DFL)) != SIG_DFL &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin handler != ignoresig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(SIGPIPE,handler); /* honor user handler */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Sfsigp = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)vtmtxunlock(_Sfmutex);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(p);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return status;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int _sfpmode(Sfio_t* f, int type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int _sfpmode(f,type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfproc_t* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(p = f->proc) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(type == SF_WRITE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* save unread data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->ndata = f->endb-f->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->ndata > p->size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(p->rdata)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free((char*)p->rdata);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((p->rdata = (uchar*)malloc(p->ndata)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->size = p->ndata;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { p->size = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->ndata > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy((Void_t*)p->rdata,(Void_t*)f->next,p->ndata);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endb = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* restore read data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->ndata > f->size) /* may lose data!!! */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->ndata = f->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->ndata > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { memcpy((Void_t*)f->data,(Void_t*)p->rdata,p->ndata);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endb = f->data+p->ndata;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->ndata = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* switch file descriptor */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->pid >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { type = f->file;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->file = p->file;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->file = type;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint _sfmode(reg Sfio_t* f, reg int wanted, reg int local)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint _sfmode(f, wanted, local)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg Sfio_t* f; /* change r/w mode and sync file pointer for this stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg int wanted; /* desired mode */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg int local; /* a local call */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfoff_t addr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int rv = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFONCE(); /* initialize mutexes */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(wanted&SF_SYNCED) /* for (SF_SYNCED|SF_READ) stream, just junk data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { wanted &= ~SF_SYNCED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->mode&(SF_SYNCED|SF_READ)) == (SF_SYNCED|SF_READ) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->next = f->endb = f->endr = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode &= ~SF_SYNCED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((!local && SFFROZEN(f)) || (!(f->flags&SF_STRING) && f->file < 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(local || !f->disc || !f->disc->exceptf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { local = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if((rv = (*f->disc->exceptf)(f,SF_LOCKED,0,f->disc)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return rv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((!local && SFFROZEN(f)) ||
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (!(f->flags&SF_STRING) && f->file < 0) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(rv == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { local = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->mode&SF_GETR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->mode &= ~SF_GETR;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef MAP_TYPE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->bits&SF_MMAP) && (f->tiny[0] += 1) >= (4*SF_NMAP) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* turn off mmap to avoid page faulting */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsetbuf(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->tiny[0] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->getr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->next[-1] = f->getr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->getr = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->mode&SF_STDIO) /* synchronizing with stdio pointers */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (*_Sfstdsync)(f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->disc == _Sfudisc && wanted == SF_WRITE &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclose((*_Sfstack)(f,NIL(Sfio_t*))) < 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { local = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->mode&SF_POOL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* move to head of pool */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f == f->pool->sf[0] || (*_Sfpmove)(f,0) < 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { local = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode &= ~SF_POOL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f,local);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* buffer initialization */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin wanted &= SF_RDWR;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->mode&SF_INIT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!f->pool && _sfsetpool(f) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { rv = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(wanted == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(wanted != (int)(f->mode&SF_RDWR) && !(f->flags&wanted) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->flags&SF_STRING) && f->size >= 0 && f->data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->mode &= ~SF_INIT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->extent = ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ?
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->size : 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->here = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endb = f->data + f->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->next = f->endr = f->endw = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->mode&SF_READ)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endr = f->endb;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else f->endw = f->endb;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { n = f->flags;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFSETBUF(f,f->data,f->size);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->flags |= (n&SF_MALLOC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(wanted == (int)SFMODE(f,1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch(SFMODE(f,1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_WRITE: /* switching to SF_READ */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(wanted == 0 || wanted == SF_WRITE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(f->flags&SF_READ) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(f->flags&SF_STRING)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SFSTRSIZE(f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endb = f->data+f->extent;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode = SF_READ;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* reset buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->next > f->data && SFFLSBUF(f,-1) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->size == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* unbuffered */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->data = f->tiny;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->size = sizeof(f->tiny);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->next = f->endr = f->endw = f->endb = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode = SF_READ|SF_LOCK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore saved read data for coprocess */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->proc && _sfpmode(f,wanted) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case (SF_READ|SF_SYNCED): /* a previously sync-ed read stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(wanted != SF_WRITE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* just reset the pointers */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode = SF_READ|SF_LOCK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see if must go with new physical location */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (addr = SFSK(f,0,SEEK_CUR,f->disc)) != f->here)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef MAP_TYPE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->bits&SF_MMAP) && f->data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SFMUNMAP(f,f->data,f->endb-f->data);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->data = NIL(uchar*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endb = f->endr = f->endw = f->next = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->here = addr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { addr = f->here + (f->endb - f->next);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(SFSK(f,addr,SEEK_SET,f->disc) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->here = addr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* fall thru */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case SF_READ: /* switching to SF_WRITE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(wanted != SF_WRITE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(!(f->flags&SF_WRITE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(f->flags&SF_STRING)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->endb = f->data+f->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode = SF_WRITE|SF_LOCK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save unread data before switching mode */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->proc && _sfpmode(f,wanted) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* reset buffer and seek pointer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(f->mode&SF_SYNCED) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { n = f->endb - f->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->extent >= 0 && (n > 0 || (f->data && (f->bits&SF_MMAP))) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* reset file pointer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr = f->here - n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(SFSK(f,addr,SEEK_SET,f->disc) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto err_notify;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->here = addr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode = SF_WRITE|SF_LOCK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef MAP_TYPE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->bits&SF_MMAP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(f->data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMUNMAP(f,f->data,f->endb-f->data);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->data == f->tiny)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->endb = f->data = f->next = NIL(uchar*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->size = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else f->endb = (f->next = f->data) + f->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default: /* unknown case */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin err_notify:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((wanted &= SF_RDWR) == 0 && (wanted = f->flags&SF_RDWR) == SF_RDWR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin wanted = SF_READ;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set errno for operations that access wrong stream type */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(wanted != (f->mode&SF_RDWR) && f->file >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = EBADF;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_Sfnotify) /* notify application of the error */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin (*_Sfnotify)(f, wanted, (void*)((long)f->file));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chindone:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFOPEN(f,local);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return rv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}