sfsetbuf.c revision 7c2fbfb345896881c631598ee3852ce9ce33fb07
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
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* *
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#if defined(__STDPP__directive) && defined(__STDPP__hide)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin__STDPP__directive pragma pp:hide getpagesize
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define getpagesize ______getpagesize
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "sfhdr.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(__STDPP__directive) && defined(__STDPP__hide)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin__STDPP__directive pragma pp:nohide getpagesize
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef getpagesize
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_getpagesize
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_BEGIN_EXTERNS_
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinextern int getpagesize _ARG_((void));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin_END_EXTERNS_
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Set a (new) buffer for a stream.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** If size < 0, it is assigned a suitable value depending on the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** kind of stream. The actual buffer size allocated is dependent
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** on how much memory is available.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_sys_stat
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct stat
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ int st_mode;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int st_size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef sysfstatf
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define sysfstatf(fd,st) (-1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_sys_stat*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int setlinemode()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ char* astsfio;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* endw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int modes = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static const char sf_line[] = "SF_LINE";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static const char sf_wcwidth[] = "SF_WCWIDTH";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ISSEPAR(c) ((c) == ',' || (c) == ' ' || (c) == '\t')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (modes < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { modes = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(astsfio = getenv("_AST_SFIO_OPTIONS"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { for(; *astsfio != 0; astsfio = endw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { while(ISSEPAR(*astsfio) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *astsfio++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(endw = astsfio; *endw && !ISSEPAR(*endw); ++endw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((endw-astsfio) == (sizeof(sf_line)-1) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strncmp(astsfio,sf_line,endw-astsfio) == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if ((modes |= SF_LINE) == (SF_LINE|SF_WCWIDTH))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((endw-astsfio) == (sizeof(sf_wcwidth)-1) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strncmp(astsfio,sf_wcwidth,endw-astsfio) == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if ((modes |= SF_WCWIDTH) == (SF_LINE|SF_WCWIDTH))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return modes;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
7c2fbfb345896881c631598ee3852ce9ce33fb07April ChinVoid_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVoid_t* sfsetbuf(f,buf,size)
7c2fbfb345896881c631598ee3852ce9ce33fb07April ChinSfio_t* f; /* stream to be buffered */
7c2fbfb345896881c631598ee3852ce9ce33fb07April ChinVoid_t* buf; /* new buffer */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinsize_t size; /* buffer size, -1 for default size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int sf_malloc, oflags, init, okmmap, local;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ssize_t bufsize, blksz;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfdisc_t* disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfstat_t st;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin uchar* obuf = NIL(uchar*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ssize_t osize = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXDECL(f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFONCE();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXENTER(f,NIL(Void_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin GETLOCAL(f,local);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size == 0 && buf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* special case to get buffer info */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Sfi = f->val = (f->bits&SF_MMAP) ? (f->endb-f->data) : f->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXRETURN(f, (Void_t*)f->data);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* cleanup actions already done, don't allow write buffering any more */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_Sfexiting && !(f->flags&SF_STRING) && (f->mode&SF_WRITE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { buf = NIL(Void_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((init = f->mode&SF_INIT) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(!f->pool && _sfsetpool(f) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXRETURN(f, NIL(Void_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((f->mode&SF_RDWR) != SFMODE(f,local) && _sfmode(f,0,local) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXRETURN(f, NIL(Void_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode = (f->mode&SF_RDWR)|SF_LOCK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { int rv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure there is no hidden read data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->proc && (f->flags&SF_READ) && (f->mode&SF_WRITE) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _sfmode(f,SF_READ,local) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXRETURN(f, NIL(Void_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* synchronize first */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f,local); rv = SFSYNC(f); SFOPEN(f,local);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rv < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXRETURN(f, NIL(Void_t*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* turn off the SF_SYNCED bit because buffer is changing */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode &= ~SF_SYNCED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f,local);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((Sfio_t*)buf != f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin blksz = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* setting alignment size only */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { blksz = (ssize_t)size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!init) /* stream already initialized */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { obuf = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin osize = f->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* initialize stream as if in the default case */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { buf = NIL(Void_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = (size_t)SF_UNBOUND;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bufsize = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin oflags = f->flags;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see if memory mapping is possible (see sfwrite for SF_BOTH) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin okmmap = (buf || (f->flags&SF_STRING) || (f->flags&SF_RDWR) == SF_RDWR) ? 0 : 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save old buffer info */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef MAP_TYPE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->bits&SF_MMAP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(f->data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SFMUNMAP(f,f->data,f->endb-f->data);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->data = NIL(uchar*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->data == f->tiny)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->data = NIL(uchar*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->size = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin obuf = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin osize = f->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->flags &= ~SF_MALLOC;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->bits &= ~SF_MMAP;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* pure read/string streams must have a valid string */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->flags&(SF_RDWR|SF_STRING)) == SF_RDSTR &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (size == (size_t)SF_UNBOUND || !buf))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set disc to the first discipline with a seekf */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(disc = f->disc; disc; disc = disc->disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(disc->seekf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((init || local) && !(f->flags&SF_STRING))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* ASSERT(f->file >= 0) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin st.st_mode = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if has discipline, set size by discipline if possible */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!_sys_stat || disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if((f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto unseekable;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { Sfoff_t e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((e = SFSK(f,(Sfoff_t)0,SEEK_END,disc)) >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->extent = e > f->here ? e : f->here;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFSK(f,f->here,SEEK_SET,disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto setbuf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* get file descriptor status */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sysfstatf((int)f->file,&st) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->here = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _sys_stat && _stat_blksize /* preferred io block size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->blksz = (size_t)st.st_blksize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bufsize = 64 * 1024;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(S_ISDIR(st.st_mode) || (Sfoff_t)st.st_size < (Sfoff_t)SF_GRAIN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin okmmap = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else f->here = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if O_TEXT /* no memory mapping with O_TEXT because read()/write() alter data stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(okmmap && f->here >= 0 &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (sysfcntlf((int)f->file,F_GETFL,0) & O_TEXT) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin okmmap = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->flags |= setlinemode();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->here >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->extent = (Sfoff_t)st.st_size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* seekable std-devices are share-public by default */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f == sfstdin || f == sfstdout || f == sfstderr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->flags |= SF_SHARE|SF_PUBLIC;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unseekable:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->extent = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->here = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(S_ISCHR(st.st_mode) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { int oerrno = errno;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bufsize = SF_GRAIN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set line mode for terminals */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(f->flags&(SF_LINE|SF_WCWIDTH)) && isatty(f->file))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->flags |= SF_LINE|SF_WCWIDTH;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _sys_stat
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* special case /dev/null */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { reg int dev, ino;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dev = (int)st.st_dev;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ino = (int)st.st_ino;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sysstatf(DEVNULL,&st) >= 0 &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dev == (int)st.st_dev &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ino == (int)st.st_ino)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFSETNULL(f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = oerrno;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* initialize side buffer for r+w unseekable streams */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!f->proc && (f->bits&SF_BOTH) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)_sfpopen(f,-1,-1,1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set page size, this is also the desired default buffer size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_Sfpage <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_getpagesize
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((_Sfpage = (size_t)getpagesize()) <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Sfpage = SF_PAGE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef MAP_TYPE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(okmmap && size && (f->mode&SF_READ) && f->extent >= 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* see if we can try memory mapping */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(disc = f->disc; disc; disc = disc->disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(disc->readf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!disc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->bits |= SF_MMAP;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size == (size_t)SF_UNBOUND)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(bufsize > _Sfpage)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = bufsize * SF_NMAP;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else size = _Sfpage * SF_NMAP;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size > 256*1024)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = 256*1024;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* get buffer space */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsetbuf:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size == (size_t)SF_UNBOUND)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* define a default size suitable for block transfer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(init && osize > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = osize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(f == sfstderr && (f->mode&SF_WRITE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(f->flags&SF_STRING )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = SF_GRAIN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((f->flags&SF_READ) && !(f->bits&SF_BOTH) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->extent > 0 && f->extent < (Sfoff_t)_Sfpage )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = (((size_t)f->extent + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((ssize_t)(size = _Sfpage) < bufsize)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = bufsize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin buf = NIL(Void_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sf_malloc = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size > 0 && !buf && !(f->bits&SF_MMAP))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* try to allocate a buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(obuf && size == (size_t)osize && init)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { buf = (Void_t*)obuf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin obuf = NIL(uchar*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sf_malloc = (oflags&SF_MALLOC);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!buf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* do allocation */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(!buf && size > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if((buf = (Void_t*)malloc(size)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else size /= 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sf_malloc = SF_MALLOC;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size == 0 && !(f->flags&SF_STRING) && !(f->bits&SF_MMAP) && (f->mode&SF_READ))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* use the internal buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = sizeof(f->tiny);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin buf = (Void_t*)f->tiny;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set up new buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->size = size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->next = f->data = f->endr = f->endw = (uchar*)buf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endb = (f->mode&SF_READ) ? f->data : f->data+size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->flags&SF_STRING)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* these fields are used to test actual size - see sfseek() */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->extent = (!sf_malloc &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ) ? size : 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->here = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* read+string stream should have all data available */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->mode&SF_READ) && !sf_malloc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endb = f->data+size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->flags = (f->flags & ~SF_MALLOC)|sf_malloc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(obuf && obuf != f->data && osize > 0 && (oflags&SF_MALLOC))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { free((Void_t*)obuf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin obuf = NIL(uchar*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chindone:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Sfi = f->val = obuf ? osize : 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* blksz is used for aligning disk block boundary while reading data to
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ** optimize data transfer from disk (eg, via direct I/O). blksz can be
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ** at most f->size/2 so that data movement in buffer can be optimized.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ** blksz should also be a power-of-2 for optimal disk seeks.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(blksz <= 0 || (blksz & (blksz-1)) != 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin blksz = SF_GRAIN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(blksz > f->size/2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin blksz /= 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->blksz = blksz;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFOPEN(f,local);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXRETURN(f, (Void_t*)obuf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}