sfsetbuf.c revision 3e14f97f673e8a630f076077de35afdd43dc1587
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* 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***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(__STDPP__directive) && defined(__STDPP__hide)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(__STDPP__directive) && defined(__STDPP__hide)
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** Written by Kiem-Phong Vo.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_sys_stat*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ISSEPAR(c) ((c) == ',' || (c) == ' ' || (c) == '\t')
7c2fbfb345896881c631598ee3852ce9ce33fb07April ChinVoid_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinsize_t size; /* buffer size, -1 for default size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* special case to get buffer info */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin _Sfi = f->val = (f->bits&SF_MMAP) ? (f->endb-f->data) : f->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* cleanup actions already done, don't allow write buffering any more */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(_Sfexiting && !(f->flags&SF_STRING) && (f->mode&SF_WRITE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((f->mode&SF_RDWR) != SFMODE(f,local) && _sfmode(f,0,local) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure there is no hidden read data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->proc && (f->flags&SF_READ) && (f->mode&SF_WRITE) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* synchronize first */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* turn off the SF_SYNCED bit because buffer is changing */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* setting alignment size only */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* initialize stream as if in the default case */
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 /* save old buffer info */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* pure read/string streams must have a valid string */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set disc to the first discipline with a seekf */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* ASSERT(f->file >= 0) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if has discipline, set size by discipline if possible */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* get file descriptor status */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _sys_stat && _stat_blksize /* preferred io block size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(S_ISDIR(st.st_mode) || (Sfoff_t)st.st_size < (Sfoff_t)SF_GRAIN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if O_TEXT /* no memory mapping with O_TEXT because read()/write() alter data stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->here >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* seekable std-devices are share-public by default */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set line mode for terminals */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(f->flags&(SF_LINE|SF_WCWIDTH)) && isatty(f->file))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* special case /dev/null */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* initialize side buffer for r+w unseekable streams */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set page size, this is also the desired default buffer size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(okmmap && size && (f->mode&SF_READ) && f->extent >= 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* see if we can try memory mapping */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* get buffer space */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* define a default size suitable for block transfer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size = (((size_t)f->extent + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* try to allocate a buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* do allocation */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size == 0 && !(f->flags&SF_STRING) && !(f->bits&SF_MMAP) && (f->mode&SF_READ))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* use the internal buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set up new buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* these fields are used to test actual size - see sfseek() */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ) ? size : 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* read+string stream should have all data available */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(obuf && obuf != f->data && osize > 0 && (oflags&SF_MALLOC))
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.