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"
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**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define MAX_SSIZE ((ssize_t)((~((size_t)0)) >> 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, reg int rc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfoff_t sfmove(fr,fw,n,rc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t* fr; /* moving data from this stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfio_t* fw; /* moving data to this stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSfoff_t n; /* number of bytes/records to move. <0 for unbounded move */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg int rc; /* record separator */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg uchar *cp, *next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg ssize_t r, w;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg uchar *endb;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int direct;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfoff_t n_move, sk, cur;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin uchar *rbuf = NIL(uchar*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ssize_t rsize = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXDECL(fr);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXDECL2(fw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXENTER(fr, (Sfoff_t)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fw)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXBEGIN2(fw, (Sfoff_t)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(n_move = 0; n != 0; )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rc >= 0) /* moving records, let sfgetr() deal with record reading */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(!(cp = (uchar*)sfgetr(fr,rc,0)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { r = sfvalue(fr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fw && (w = SFWRITE(fw, cp, r)) != r)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(fr->extent >= 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFSEEK(fr,(Sfoff_t)(-r),SEEK_CUR);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fw->extent >= 0 && w > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFSEEK(fw,(Sfoff_t)(-w),SEEK_CUR);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { n_move += 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n -= 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* get the streams into the right mode */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fr->mode != SF_READ && _sfmode(fr,SF_READ,0) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(fr,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* flush the write buffer as necessary to make room */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(fw->mode != SF_WRITE && _sfmode(fw,SF_WRITE,0) < 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(fw,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fw->next >= fw->endb ||
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (fw->next > fw->data && fr->extent < 0 &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (fw->extent < 0 || (fw->flags&SF_SHARE)) ) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(SFFLSBUF(fw,-1) < 0 )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
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 { n_move += sk - cur;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n -= sk - cur;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* else: stream unstacking may happen below */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* about to move all, set map to a large amount */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n < 0 && (fr->bits&SF_MMAP) && !(fr->bits&SF_MVSIZE) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SFMVSET(fr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fr->bits |= SF_SEQUENTIAL; /* sequentially access data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* try reading a block of data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin direct = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((r = fr->endb - (next = fr->next)) <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* amount of data remained to be read */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((w = n > MAX_SSIZE ? MAX_SSIZE : (ssize_t)n) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(fr->extent < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin w = fr->data == fr->tiny ? SF_GRAIN : fr->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((fr->extent-fr->here) > SF_NMAP*SF_PAGE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin w = SF_NMAP*SF_PAGE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else w = (ssize_t)(fr->extent-fr->here);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* use a decent buffer for data transfer but make sure
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin that if we overread, the left over can be retrieved
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(fr->flags&SF_STRING) && !(fr->bits&SF_MMAP) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (n < 0 || fr->extent >= 0) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { reg ssize_t maxw = 4*(_Sfpage > 0 ? _Sfpage : SF_PAGE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* direct transfer to a seekable write stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fw && fw->extent >= 0 && w <= (fw->endb-fw->next) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { w = fw->endb - (next = fw->next);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin direct = SF_WRITE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(w > fr->size && maxw > fr->size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* making our own buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(w >= maxw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin w = maxw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else w = ((w+fr->size-1)/fr->size)*fr->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rsize <= 0 && (rbuf = (uchar*)malloc(w)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rsize = w;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rbuf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { next = rbuf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin w = rsize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin direct = SF_STRING;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!direct)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* make sure we don't read too far ahead */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n > 0 && fr->extent < 0 && (fr->flags&SF_SHARE) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if((Sfoff_t)(r = fr->size) > n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = (ssize_t)n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else r = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((r = SFFILBUF(fr,r)) <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin next = fr->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* actual amount to be read */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n > 0 && n < w)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin w = (ssize_t)n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((r = SFRD(fr,next,w,fr->disc)) > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fr->next = fr->endb = fr->endr = fr->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(r == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break; /* eof */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else goto again; /* popped stack */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* compute the extent of data to be moved */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin endb = next+r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(r > n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = (ssize_t)n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n -= r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n_move += r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp = next+r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!direct)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fr->next += r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((w = endb-cp) > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* move left-over to read stream */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(w > fr->size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin w = fr->size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy((Void_t*)fr->data,(Void_t*)cp,w);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fr->endb = fr->data+w;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((w = endb - (cp+w)) > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFSK(fr,(Sfoff_t)(-w),SEEK_CUR,fr->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(direct == SF_WRITE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fw->next += r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(r <= (fw->endb-fw->next) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { memcpy((Void_t*)fw->next,(Void_t*)next,r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fw->next += r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((w = SFWRITE(fw,(Void_t*)next,r)) != r)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* a write error happened */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(w > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { r -= w;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n_move -= r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fr->extent >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFSEEK(fr,(Sfoff_t)(-r),SEEK_CUR);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin again:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFOPEN(fr,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFOPEN(fw,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n < 0 && (fr->bits&SF_MMAP) && (fr->bits&SF_MVSIZE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* back to normal access mode */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMVUNSET(fr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((fr->bits&SF_SEQUENTIAL) && (fr->data))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMMSEQOFF(fr,fr->data,fr->endb-fr->data);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fr->bits &= ~SF_SEQUENTIAL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rbuf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(rbuf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SFOPEN(fw,0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXEND2(fw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFOPEN(fr,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXRETURN(fr, n_move);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}