/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#include "sfhdr.h"
/* Set the IO pointer to a specific location in the stream
**
** Written by Kiem-Phong Vo.
*/
#if __STD_C
#else
static void newpos(f, p)
Sfio_t* f;
Sfoff_t p;
#endif
{
#ifdef MAP_TYPE
}
#endif
if((f->here = p) < 0)
{ f->extent = -1;
f->here = 0;
}
}
#if __STD_C
#else
Sfio_t* f; /* seek to a new location in this stream */
Sfoff_t p; /* place to seek to */
int type; /* 0: from org, 1: from here, 2: from end */
#endif
{
Sfoff_t r, s;
SFMTXDECL(f);
}
/* set and initialize the stream to a definite mode */
if(mode < 0)
}
/* Xopen-compliant */
}
if(f->extent < 0)
{ /* let system call set errno */
}
/* throw away ungetc data */
/* lock the stream for internal manipulations */
/* clear error and eof bits */
{ SFSTRSIZE(f);
r = p + f->extent;
else r = p;
if(r >= 0 && r <= f->size)
{ p = r;
f->here = p;
if(p > f->extent)
goto done;
}
/* check exception handler, note that this may pop stream */
{ p = -1;
goto done;
}
{ p = r;
goto done;
}
}
{ /* see if we can avoid flushing buffer */
if(r == s)
{ p = r;
goto done;
}
}
{ p = -1;
goto done;
}
}
else
}
if(p >= 0)
newpos(f,p);
goto done;
}
/* if get here, must be a read stream */
goto near_done;
else if(s < 0)
{ p = -1;
goto done;
}
else
{ newpos(f,s);
hardseek = 0;
}
}
else
{ near_done:
p = r;
goto done;
}
}
/* desired position */
goto done;
#ifdef MAP_TYPE
{ /* if mmap is not great, stop mmaping if moving around too much */
#if _mmap_worthy < 2
}
else
#endif
{ /* for mmap, f->here can be virtual except for hardseek */
newpos(f,p);
if(!hardseek)
goto done;
}
}
#endif
{ /* reduce wastage in future buffer fillings */
}
f->iosz = 0;
/* buffer is now considered empty */
/* small backseeks often come in bunches, so seek back as far as possible */
{ if((r = s - f->size) < 0)
r = 0;
}
/* try to align buffer to block boundary to enhance I/O speed */
r = p - (p%f->blksz);
else
{ r = p;
/* seeking around and wasting data, be conservative */
f->bits |= SF_JUSTSEEK;
}
{ if(r < p) /* now try to just get to p */
if(f->here != p)
p = -1;
goto done;
}
if(r < p) /* read to cover p */
else /* recover from read failure by just seeking to p */
p = -1;
}
}
done :
if(f->here < 0) /* hasn't been the best of time */
{ f->extent = -1;
f->here = 0;
}
f->lpos = p;
if(mustsync)
sfsync(f);
SFMTXRETURN(f, p);
}