fseek.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:8k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* fseek.c - seek a position in a file. stdio.h */
  2. /* Copyright 1992-1993 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01d,05feb99,dgp  document errno values
  7. 01c,05mar93,jdi  documentation cleanup for 5.1.
  8. 01b,20sep92,smb  documentation additions
  9. 01a,29jul92,jcf  Added OBJ_VERIFY
  10.    +smb  taken from UCB stdio, removed fstat().
  11. */
  12. /*
  13. DESCRIPTION
  14.  * Copyright (c) 1990 The Regents of the University of California.
  15.  * All rights reserved.
  16.  *
  17.  * This code is derived from software contributed to Berkeley by
  18.  * Chris Torek.
  19.  *
  20.  * Redistribution and use in source and binary forms, with or without
  21.  * modification, are permitted provided that the following conditions
  22.  * are met:
  23.  * 1. Redistributions of source code must retain the above copyright
  24.  *    notice, this list of conditions and the following disclaimer.
  25.  * 2. Redistributions in binary form must reproduce the above copyright
  26.  *    notice, this list of conditions and the following disclaimer in the
  27.  *    documentation and/or other materials provided with the distribution.
  28.  * 3. All advertising materials mentioning features or use of this software
  29.  *    must display the following acknowledgement:
  30.  * This product includes software developed by the University of
  31.  * California, Berkeley and its contributors.
  32.  * 4. Neither the name of the University nor the names of its contributors
  33.  *    may be used to endorse or promote products derived from this software
  34.  *    without specific prior written permission.
  35.  *
  36.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  37.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  38.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  39.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  40.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  41.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  42.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  44.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  45.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47. INCLUDE FILE: stdio.h, sys/types.h, sys/stat.h, fcntl.h, stdlib.h, errno.h
  48. SEE ALSO: American National Standard X3.159-1989
  49. NOMANUAL
  50. */
  51. #include "vxWorks.h"
  52. #include "stdio.h"
  53. #include "ioLib.h"
  54. #include "sys/types.h"
  55. #include "sys/stat.h"
  56. #include "fcntl.h"
  57. #include "stdlib.h"
  58. #include "errno.h"
  59. #include "objLib.h"
  60. #include "private/stdioP.h"
  61. #define POS_ERR (-(fpos_t)1)
  62. /******************************************************************************
  63. *
  64. * fseek - set the file position indicator for a stream (ANSI)
  65. *
  66. * This routine sets the file position indicator for a specified stream.
  67. * For a binary stream, the new position, measured in characters from the 
  68. * beginning of the file, is obtained by adding <offset> to the position 
  69. * specified by <whence>, whose possible values are:
  70. * .iP SEEK_SET 16
  71. * the beginning of the file.
  72. * .iP SEEK_CUR
  73. * the current value of the file position indicator.
  74. * .iP SEEK_END
  75. * the end of the file.
  76. * .LP
  77. * A binary stream does not meaningfully
  78. * support fseek() calls with a <whence> value of SEEK_END.
  79. *
  80. * For a text stream, either <offset> is zero, or <offset> is a value
  81. * returned by an earlier call to ftell() on the stream, in which case
  82. * <whence> should be SEEK_SET.
  83. *
  84. * A successful call to fseek() clears the end-of-file indicator for the
  85. * stream and undoes any effects of ungetc() on the same stream.  After an
  86. * fseek() call, the next operation on an update stream can be either input
  87. * or output.
  88. * INCLUDE FILES: stdio.h 
  89. *
  90. * RETURNS: Non-zero only for a request that cannot be satisfied.
  91. *
  92. * ERRNO: EINVAL
  93. *
  94. * SEE ALSO: ftell()
  95. */
  96. int fseek
  97.     (
  98.     FAST FILE * fp, /* stream */
  99.     long offset, /* offset from <whence> */
  100.     int whence /* position to offset from: */
  101. /* SEEK_SET = beginning */
  102. /* SEEK_CUR = current position */
  103. /* SEEK_END = end-of-file */
  104.     )
  105.     {
  106.     fpos_t target;
  107.     fpos_t curoff;
  108.     size_t n;
  109.     struct stat st;
  110.     int havepos;
  111.     BOOL doStat;
  112.     if (OBJ_VERIFY (fp, fpClassId) != OK)
  113. return (ERROR);
  114.     /*
  115.      * Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
  116.      * After this, whence is either SEEK_SET or SEEK_END.
  117.      */
  118.     switch (whence) 
  119. {
  120. case SEEK_CUR:
  121. /*
  122.  * In order to seek relative to the current stream offset,
  123.  * we have to first find the current stream offset a la
  124.  * ftell (see ftell for details).
  125.  */
  126. if (fp->_flags & __SOFF)
  127.     curoff = fp->_offset;
  128. else 
  129.     {
  130.     curoff = __sseek (fp, (fpos_t)0, SEEK_CUR);
  131.     if (curoff == -1L)
  132. return (EOF);
  133.     }
  134. if (fp->_flags & __SRD) 
  135.     {
  136.     curoff -= fp->_r;
  137.     if (HASUB(fp))
  138. curoff -= fp->_ur;
  139.     }
  140. else if (fp->_flags & __SWR && fp->_p != NULL)
  141.     curoff += fp->_p - fp->_bf._base;
  142. offset += curoff;
  143. whence = SEEK_SET;
  144. havepos = 1;
  145. break;
  146. case SEEK_SET:
  147. case SEEK_END:
  148. curoff = 0; /* XXX just to keep gcc quiet */
  149. havepos = 0;
  150. break;
  151. default:
  152. errno = EINVAL;
  153. return (EOF);
  154. }
  155.     /*
  156.      * Can only optimise if:
  157.      * reading (and not reading-and-writing);
  158.      * not unbuffered; and
  159.      * this is a `regular' Unix file (and hence seekfn==__sseek).
  160.      * We must check __NBF first, because it is possible to have __NBF
  161.      * and __SOPT both set.
  162.      */
  163.     if (fp->_bf._base == NULL)
  164. __smakebuf (fp);
  165.     if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT))
  166. goto dumb;
  167.     doStat = ioctl (fp->_file, FIOFSTATGET, (int)&st);
  168.     if ((fp->_flags & __SOPT) == 0) 
  169. {
  170. if ((fp->_file < 0 || (doStat) ||
  171.     (st.st_mode & S_IFMT) != S_IFREG)) 
  172.     {
  173.     fp->_flags |= __SNPT;
  174.     goto dumb;
  175.     }
  176. fp->_blksize   = st.st_blksize;
  177. fp->_flags |= __SOPT;
  178. }
  179.     /*
  180.      * We are reading; we can try to optimise.
  181.      * Figure out where we are going and where we are now.
  182.      */
  183.     if (whence == SEEK_SET)
  184. target = offset;
  185.     else 
  186. {
  187. if (doStat)
  188.     goto dumb;
  189. target = st.st_size + offset;
  190. }
  191.     if (!havepos) 
  192. {
  193. if (fp->_flags & __SOFF)
  194.     curoff = fp->_offset;
  195. else 
  196.     {
  197.     curoff = __sseek (fp, 0L, SEEK_CUR);
  198.     if (curoff == POS_ERR)
  199. goto dumb;
  200.     }
  201. curoff -= fp->_r;
  202. if (HASUB(fp))
  203.     curoff -= fp->_ur;
  204. }
  205.     /*
  206.      * Compute the number of bytes in the input buffer (pretending
  207.      * that any ungetc() input has been discarded).  Adjust current
  208.      * offset backwards by this count so that it represents the
  209.      * file offset for the first byte in the current input buffer.
  210.      */
  211.     if (HASUB(fp)) 
  212. {
  213. n = fp->_up - fp->_bf._base;
  214. curoff -= n;
  215. n      += fp->_ur;
  216.     else 
  217. {
  218. n = fp->_p - fp->_bf._base;
  219. curoff -= n;
  220. n      += fp->_r;
  221. }
  222.     /*
  223.      * If the target offset is within the current buffer,
  224.      * simply adjust the pointers, clear EOF, undo ungetc(),
  225.      * and return.  (If the buffer was modified, we have to
  226.      * skip this; see fgetline.c.)
  227.      */
  228.     if (((fp->_flags & __SMOD) == 0) && 
  229. (target >= curoff) && 
  230. (target < (curoff + n))) 
  231. {
  232. FAST int o = target - curoff;
  233. fp->_p = fp->_bf._base + o;
  234. fp->_r = n - o;
  235. if (HASUB(fp))
  236.     FREEUB(fp);
  237. fp->_flags &= ~__SEOF;
  238. return (0);
  239. }
  240.     /*
  241.      * The place we want to get to is not within the current buffer,
  242.      * but we can still be kind to the kernel copyout mechanism.
  243.      * By aligning the file offset to a block boundary, we can let
  244.      * the kernel use the VM hardware to map pages instead of
  245.      * copying bytes laboriously.  Using a block boundary also
  246.      * ensures that we only read one block, rather than two.
  247.      */
  248.     curoff = target & ~(fp->_blksize - 1);
  249.     if (__sseek (fp, curoff, SEEK_SET) == POS_ERR)
  250. goto dumb;
  251.     fp->_r = 0;
  252.     if (HASUB(fp))
  253. FREEUB(fp);
  254.     fp->_flags &= ~__SEOF;
  255.     n = target - curoff;
  256.     if (n) 
  257. {
  258. if (__srefill (fp) || fp->_r < n)
  259.     goto dumb;
  260. fp->_p += n;
  261. fp->_r -= n;
  262. }
  263.     return (0);
  264.     /*
  265.      * We get here if we cannot optimise the seek ... just
  266.      * do it.  Allow the seek function to change fp->_bf._base.
  267.      */
  268. dumb:
  269.     if ((__sflush (fp)) || (__sseek (fp, offset, whence) == POS_ERR)) 
  270. return (EOF);
  271.     /* success: clear EOF indicator and discard ungetc() data */
  272.     if (HASUB(fp))
  273. FREEUB(fp);
  274.     fp->_p = fp->_bf._base;
  275.     fp->_r = 0;
  276.     /* fp->_w = 0; */ /* unnecessary (I think...) */
  277.     fp->_flags &= ~__SEOF;
  278.     return (0);
  279.     }