home *** CD-ROM | disk | FTP | other *** search
- /***
- *fseek.c - reposition file pointer on a stream
- *
- * Copyright (c) 1985-1997, 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);
-
- retval = _fseek_lk (stream, offset, whence);
-
- _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);
- #if !defined (_M_MPPC) && !defined (_M_M68K)
- else if ( (stream->_flag & _IOREAD) && (stream->_flag & _IOMYBUF) &&
- !(stream->_flag & _IOSETVBUF) )
- stream->_bufsiz = _SMALL_BUFSIZ;
- #endif /* !defined (_M_MPPC) && !defined (_M_M68K) */
-
- /* Seek to the desired locale and return. */
-
- return(_lseek(_fileno(stream), offset, whence) == -1L ? -1 : 0);
- }
-