sfmode.c revision 7c2fbfb345896881c631598ee3852ce9ce33fb07
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* Copyright (c) 1985-2008 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* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic char* Version = "\n@(#)$Id: sfio (AT&T Research) 2008-07-17 $\0\n";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Functions to set a given stream to some desired mode
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo.
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.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* the below is for protecting the application from SIGPIPE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int _Sfsigp = 0; /* # of streams needing SIGPIPE protection */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* done at exiting time */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void _sfcleanup(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void _sfcleanup()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set this so that no more buffering is allowed for write streams */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { for(n = 0; n < p->n_sf; ++n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* let application know that we are leaving */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* from now on, write streams are unbuffered */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* put into discrete pool */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(p = f->pool) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* allocate a larger array */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { n = (p->sf != p->array ? p->s_sf : (p->s_sf/4 + 1)*4) + 4;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* move old array to new one */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy((Void_t*)array,(Void_t*)p->sf,p->n_sf*sizeof(Sfio_t*));
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/* create an auxiliary buffer for sfgetr/sfreserve/sfputr */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make buffer if nothing yet */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint stdio; /* stdio popen() does not reset SIGPIPE handler */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(p = f->proc = (Sfproc_t*)malloc(sizeof(Sfproc_t))) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->sigp = (!stdio && pid >= 0 && (f->flags&SF_WRITE)) ? 1 : 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(p = f->proc))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->pid < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* close the associated stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->file >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* wait for process termination */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while ((pid = waitpid(p->pid,&status,0)) == -1 && errno == EINTR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(p = f->proc) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* save unread data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* restore read data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* switch file descriptor */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(p->pid >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint _sfmode(reg Sfio_t* f, reg int wanted, reg int local)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg Sfio_t* f; /* change r/w mode and sync file pointer for this stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(wanted&SF_SYNCED) /* for (SF_SYNCED|SF_READ) stream, just junk data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->mode&(SF_SYNCED|SF_READ)) == (SF_SYNCED|SF_READ) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((!local && SFFROZEN(f)) || (!(f->flags&SF_STRING) && f->file < 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if((rv = (*f->disc->exceptf)(f,SF_LOCKED,0,f->disc)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(rv == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->bits&SF_MMAP) && (f->tiny[0] += 1) >= (4*SF_NMAP) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* turn off mmap to avoid page faulting */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->tiny[0] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->mode&SF_STDIO) /* synchronizing with stdio pointers */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* move to head of pool */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* buffer initialization */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(wanted != (int)(f->mode&SF_RDWR) && !(f->flags&wanted) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->extent = ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ?
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* reset buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->size == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* unbuffered */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore saved read data for coprocess */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case (SF_READ|SF_SYNCED): /* a previously sync-ed read stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* just reset the pointers */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see if must go with new physical location */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* fall thru */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save unread data before switching mode */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* reset buffer and seek pointer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->extent >= 0 && (n > 0 || (f->data && (f->bits&SF_MMAP))) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* reset file pointer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default: /* unknown case */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((wanted &= SF_RDWR) == 0 && (wanted = f->flags&SF_RDWR) == SF_RDWR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set errno for operations that access wrong stream type */