diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2012-11-29 16:28:30 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2012-11-29 16:28:30 +0000 |
commit | 0772f3f1c18483ff69b4a4cec918df39596eae5c (patch) | |
tree | ad788e069002f5924f39d5f624368177a6223d97 /newlib/libc/stdio/fseek.c | |
parent | 0d829d9695a57a37203b1ef1e4ca812bd1fb2fb1 (diff) | |
download | cygnal-0772f3f1c18483ff69b4a4cec918df39596eae5c.tar.gz cygnal-0772f3f1c18483ff69b4a4cec918df39596eae5c.tar.bz2 cygnal-0772f3f1c18483ff69b4a4cec918df39596eae5c.zip |
* libc/include/sys/reent.h (__sFILE): Change type of _offset
from int to _off_t.
* libc/stdio/ftell.c: Use _ftello_r().
* libc/stdio/ftello.c: Copy implementation from previous
_ftell_r().
* libc/stdio/fseek.c: Use _fseeko_r().
* libc/stdio/fseeko.c: Copy implementation from previous
_fseek_r().
Diffstat (limited to 'newlib/libc/stdio/fseek.c')
-rw-r--r-- | newlib/libc/stdio/fseek.c | 271 |
1 files changed, 1 insertions, 270 deletions
diff --git a/newlib/libc/stdio/fseek.c b/newlib/libc/stdio/fseek.c index 099a95892..34147faff 100644 --- a/newlib/libc/stdio/fseek.c +++ b/newlib/libc/stdio/fseek.c @@ -101,21 +101,9 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, #include <_ansi.h> #include <reent.h> #include <stdio.h> -#include <string.h> -#include <time.h> -#include <fcntl.h> -#include <stdlib.h> #include <errno.h> -#include <sys/stat.h> #include "local.h" -#define POS_ERR (-(_fpos_t)1) - -/* - * Seek the given file to the given offset. - * `Whence' must be one of the three SEEK_* macros. - */ - int _DEFUN(_fseek_r, (ptr, fp, offset, whence), struct _reent *ptr _AND @@ -123,264 +111,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), long offset _AND int whence) { - _fpos_t _EXFNPTR(seekfn, (struct _reent *, _PTR, _fpos_t, int)); - _fpos_t target; - _fpos_t curoff = 0; - size_t n; -#ifdef __USE_INTERNAL_STAT64 - struct stat64 st; -#else - struct stat st; -#endif - int havepos; - - /* Make sure stdio is set up. */ - - CHECK_INIT (ptr, fp); - - _newlib_flockfile_start (fp); - - /* If we've been doing some writing, and we're in append mode - then we don't really know where the filepos is. */ - - if (fp->_flags & __SAPP && fp->_flags & __SWR) - { - /* So flush the buffer and seek to the end. */ - _fflush_r (ptr, fp); - } - - /* Have to be able to seek. */ - - if ((seekfn = fp->_seek) == NULL) - { - ptr->_errno = ESPIPE; /* ??? */ - _newlib_flockfile_exit (fp); - return EOF; - } - - /* - * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. - * After this, whence is either SEEK_SET or SEEK_END. - */ - - switch (whence) - { - case SEEK_CUR: - /* - * In order to seek relative to the current stream offset, - * we have to first find the current stream offset a la - * ftell (see ftell for details). - */ - _fflush_r (ptr, fp); /* may adjust seek offset on append stream */ - if (fp->_flags & __SOFF) - curoff = fp->_offset; - else - { - curoff = seekfn (ptr, fp->_cookie, (_fpos_t) 0, SEEK_CUR); - if (curoff == -1L) - { - _newlib_flockfile_exit (fp); - return EOF; - } - } - if (fp->_flags & __SRD) - { - curoff -= fp->_r; - if (HASUB (fp)) - curoff -= fp->_ur; - } - else if (fp->_flags & __SWR && fp->_p != NULL) - curoff += fp->_p - fp->_bf._base; - - offset += curoff; - whence = SEEK_SET; - havepos = 1; - break; - - case SEEK_SET: - case SEEK_END: - havepos = 0; - break; - - default: - ptr->_errno = EINVAL; - _newlib_flockfile_exit (fp); - return (EOF); - } - - /* - * Can only optimise if: - * reading (and not reading-and-writing); - * not unbuffered; and - * this is a `regular' Unix file (and hence seekfn==__sseek). - * We must check __NBF first, because it is possible to have __NBF - * and __SOPT both set. - */ - - if (fp->_bf._base == NULL) - __smakebuf_r (ptr, fp); - if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT)) - goto dumb; - if ((fp->_flags & __SOPT) == 0) - { - if (seekfn != __sseek - || fp->_file < 0 -#ifdef __USE_INTERNAL_STAT64 - || _fstat64_r (ptr, fp->_file, &st) -#else - || _fstat_r (ptr, fp->_file, &st) -#endif - || (st.st_mode & S_IFMT) != S_IFREG) - { - fp->_flags |= __SNPT; - goto dumb; - } -#ifdef HAVE_BLKSIZE - fp->_blksize = st.st_blksize; -#else - fp->_blksize = 1024; -#endif - fp->_flags |= __SOPT; - } - - /* - * We are reading; we can try to optimise. - * Figure out where we are going and where we are now. - */ - - if (whence == SEEK_SET) - target = offset; - else - { -#ifdef __USE_INTERNAL_STAT64 - if (_fstat64_r (ptr, fp->_file, &st)) -#else - if (_fstat_r (ptr, fp->_file, &st)) -#endif - goto dumb; - target = st.st_size + offset; - } - if ((long)target != target) - { - ptr->_errno = EOVERFLOW; - _newlib_flockfile_exit (fp); - return EOF; - } - - if (!havepos) - { - if (fp->_flags & __SOFF) - curoff = fp->_offset; - else - { - curoff = seekfn (ptr, fp->_cookie, 0L, SEEK_CUR); - if (curoff == POS_ERR) - goto dumb; - } - curoff -= fp->_r; - if (HASUB (fp)) - curoff -= fp->_ur; - } - - /* - * Compute the number of bytes in the input buffer (pretending - * that any ungetc() input has been discarded). Adjust current - * offset backwards by this count so that it represents the - * file offset for the first byte in the current input buffer. - */ - - if (HASUB (fp)) - { - curoff += fp->_r; /* kill off ungetc */ - n = fp->_up - fp->_bf._base; - curoff -= n; - n += fp->_ur; - } - else - { - n = fp->_p - fp->_bf._base; - curoff -= n; - n += fp->_r; - } - - /* - * If the target offset is within the current buffer, - * simply adjust the pointers, clear EOF, undo ungetc(), - * and return. - */ - - if (target >= curoff && target < curoff + n) - { - register int o = target - curoff; - - fp->_p = fp->_bf._base + o; - fp->_r = n - o; - if (HASUB (fp)) - FREEUB (ptr, fp); - fp->_flags &= ~__SEOF; - memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); - _newlib_flockfile_exit (fp); - return 0; - } - - /* - * The place we want to get to is not within the current buffer, - * but we can still be kind to the kernel copyout mechanism. - * By aligning the file offset to a block boundary, we can let - * the kernel use the VM hardware to map pages instead of - * copying bytes laboriously. Using a block boundary also - * ensures that we only read one block, rather than two. - */ - - curoff = target & ~(fp->_blksize - 1); - if (seekfn (ptr, fp->_cookie, curoff, SEEK_SET) == POS_ERR) - goto dumb; - fp->_r = 0; - fp->_p = fp->_bf._base; - if (HASUB (fp)) - FREEUB (ptr, fp); - fp->_flags &= ~__SEOF; - n = target - curoff; - if (n) - { - if (__srefill_r (ptr, fp) || fp->_r < n) - goto dumb; - fp->_p += n; - fp->_r -= n; - } - memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); - _newlib_flockfile_exit (fp); - return 0; - - /* - * We get here if we cannot optimise the seek ... just - * do it. Allow the seek function to change fp->_bf._base. - */ - -dumb: - if (_fflush_r (ptr, fp) - || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR) - { - _newlib_flockfile_exit (fp); - return EOF; - } - /* success: clear EOF indicator and discard ungetc() data */ - if (HASUB (fp)) - FREEUB (ptr, fp); - fp->_p = fp->_bf._base; - fp->_r = 0; - /* fp->_w = 0; *//* unnecessary (I think...) */ - fp->_flags &= ~__SEOF; - /* Reset no-optimization flag after successful seek. The - no-optimization flag may be set in the case of a read - stream that is flushed which by POSIX/SUSv3 standards, - means that a corresponding seek must not optimize. The - optimization is then allowed if no subsequent flush - is performed. */ - fp->_flags &= ~__SNPT; - memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); - _newlib_flockfile_end (fp); - return 0; + return _fseeko_r (ptr, fp, offset, whence); } #ifndef _REENT_ONLY |