69,381
社区成员
发帖
与我相关
我的任务
分享
/***
*fseek.c - reposition file pointer on a stream
*
* Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines fseek() - move the file pointer to new place in file
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <file2.h>
#include <dbgint.h>
#include <msdos.h>
#include <errno.h>
#include <malloc.h>
#include <io.h>
#include <stddef.h>
#include <internal.h>
#include <mtdll.h>
/***
*int fseek(stream, offset, whence) - reposition file pointer
*
*Purpose:
*
* Reposition file pointer to the desired location. The new location
* is calculated as follows:
* { whence=0, beginning of file }
* <offset> bytes + { whence=1, current position }
* { whence=2, end of file }
*
* Be careful to coordinate with buffering.
*
* - - - - - - - - - - - - -
*
* [NOTE: We used to bend over backwards to try and preserve the current
* buffer and maintain disk block alignment. This ended up making our
* code big and slow and complicated, and slowed us down quite a bit.
* Some of the things pertinent to the old implimentation:
*
* (1) Read-only: We only did the special code path if the file was
* opened read-only (_IOREAD). If the file was writable, we didn't
* try to optimize.
*
* (2) Buffering: We'd assign a buffer, if necessary, since the
* later code might need it (i.e., call _getbuf).
*
* (3) Ungetc: Fseek had to be careful NOT to save the buffer if
* an ungetc had ever been done on the buffer (flag _IOUNGETC).
*
* (4) Control ^Z: Fseek had to deal with ^Z after reading a
* new buffer's worth of data (flag _IOCTRLZ).
*
* (5) Seek-to-end-and-back: To determine if the new seek was within
* the current buffer, we had to 'normalize' the desired location.
* This means that we sometimes had to seek to the end of the file
* and back to determine what the 0-relative offset was. Two extra
* lseek() calls hurt performance.
*
* (6) CR/LF accounting - When trying to seek within a buffer that
* is in text mode, we had to go account for CR/LF expansion. This
* required us to look at every character up to the new offset and
* see if it was '\n' or not. In addition, we had to check the
* FCRLF flag to see if the new buffer started with '\n'.
*
* Again, all of these notes are for the OLD implimentation just to
* remind folks of some of the issues involving seeking within a buffer
* and maintaining buffer alignment. As an aside, I think this may have
* been a big win in the 'old days' on floppy-based systems but on newer
* fast hard disks, the extra code/complexity overwhelmed any gain.
*
* - - - - - - - - - - - - -
*
*Entry:
* FILE *stream - file to reposition file pointer on
* long offset - offset to seek to
* int whence - origin offset is measured from (0=beg, 1=current pos,
* 2=end)
*
*Exit:
* returns 0 if succeeds
* returns -1 and sets errno if fails
* fields of FILE struct will be changed
*
*Exceptions:
*
*******************************************************************************/
#ifdef _MT
int __cdecl fseek (
FILE *stream,
long offset,
int whence
)
{
int retval;
_ASSERTE(stream != NULL);
_lock_str(stream);
__try {
retval = _fseek_lk (stream, offset, whence);
}
__finally {
_unlock_str(stream);
}
return(retval);
}
/***
*_fseek_lk() - Core fseek() routine (stream is locked)
*
*Purpose:
* Core fseek() routine; assumes that caller has the stream locked.
*
* [See fseek() for more info.]
*
*Entry: [See fseek()]
*
*Exit: [See fseek()]
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _fseek_lk (
#else /* _MT */
int __cdecl fseek (
#endif /* _MT */
FILE *str,
long offset,
int whence
)
{
REG1 FILE *stream;
_ASSERTE(str != NULL);
/* Init stream pointer */
stream = str;
if ( !inuse(stream) || ((whence != SEEK_SET) && (whence != SEEK_CUR) &&
(whence != SEEK_END)) ) {
errno=EINVAL;
return(-1);
}
/* Clear EOF flag */
stream->_flag &= ~_IOEOF;
/* If seeking relative to current location, then convert to
a seek relative to beginning of file. This accounts for
buffering, etc. by letting fseek() tell us where we are. */
if (whence == SEEK_CUR) {
offset += _ftell_lk(stream);
whence = SEEK_SET;
}
/* Flush buffer as necessary */
_flush(stream);
/* If file opened for read/write, clear flags since we don't know
what the user is going to do next. If the file was opened for
read access only, decrease _bufsiz so that the next _filbuf
won't cost quite so much */
if (stream->_flag & _IORW)
stream->_flag &= ~(_IOWRT|_IOREAD);
else if ( (stream->_flag & _IOREAD) && (stream->_flag & _IOMYBUF) &&
!(stream->_flag & _IOSETVBUF) )
stream->_bufsiz = _SMALL_BUFSIZ;
/* Seek to the desired locale and return. */
return(_lseek(_fileno(stream), offset, whence) == -1L ? -1 : 0);
}