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/* Move data from one stream to another.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** This code is written so that it'll work even in the presence
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** of stacking streams, pool, and discipline.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** If you must change it, be gentle.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, reg int rc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfoff_t n; /* number of bytes/records to move. <0 for unbounded move */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(n_move = 0; n != 0; )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rc >= 0) /* moving records, let sfgetr() deal with record reading */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* get the streams into the right mode */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* flush the write buffer as necessary to make room */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(fw->mode != SF_WRITE && _sfmode(fw,SF_WRITE,0) < 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((cur = SFSEEK(fr, (Sfoff_t)0, SEEK_CUR)) >= 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { sk = n > 0 ? SFSEEK(fr, n, SEEK_CUR) : SFSEEK(fr, 0, SEEK_END);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sk > cur) /* safe to skip over data in current stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* else: stream unstacking may happen below */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* about to move all, set map to a large amount */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n < 0 && (fr->bits&SF_MMAP) && !(fr->bits&SF_MVSIZE) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fr->bits |= SF_SEQUENTIAL; /* sequentially access data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* try reading a block of data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* amount of data remained to be read */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* use a decent buffer for data transfer but make sure
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin that if we overread, the left over can be retrieved
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { reg ssize_t maxw = 4*(_Sfpage > 0 ? _Sfpage : SF_PAGE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* direct transfer to a seekable write stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* making our own buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* make sure we don't read too far ahead */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else r = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* actual amount to be read */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n > 0 && n < w)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(r == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break; /* eof */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* compute the extent of data to be moved */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(r > n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* move left-over to read stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* a write error happened */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n < 0 && (fr->bits&SF_MMAP) && (fr->bits&SF_MVSIZE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* back to normal access mode */