fseek.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:7k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * Copyright (c) 1993, 1994 Chris Provenzano. 
  4.  * All rights reserved.
  5.  *
  6.  * This code is derived from software contributed to Berkeley by
  7.  * Chris Torek.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  * This product includes software developed by the University of
  20.  * California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #if defined(LIBC_SCCS) && !defined(lint)
  38. /*static char *sccsid = "from: @(#)fseek.c 5.7 (Berkeley) 2/24/91";*/
  39. static char *rcsid = "$Id$";
  40. #endif /* LIBC_SCCS and not lint */
  41. #include <pthread.h>
  42. #include <sys/types.h>
  43. #include <sys/stat.h>
  44. #include <fcntl.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <errno.h>
  48. #include "local.h"
  49. #define POS_ERR (-(fpos_t)1)
  50. /*
  51.  * Seek the given file to the given offset.
  52.  * `Whence' must be one of the three SEEK_* macros.
  53.  */
  54. fseek(fp, offset, whence)
  55. register FILE *fp;
  56. long offset;
  57. int whence;
  58. {
  59. #if __STDC__
  60. register fpos_t (*seekfn)(void *, fpos_t, int);
  61. #else
  62. register fpos_t (*seekfn)();
  63. #endif
  64. fpos_t target, curoff;
  65. size_t n;
  66. struct stat st;
  67. int havepos;
  68. /* make sure stdio is set up */
  69. __sinit ();
  70. flockfile(fp);
  71. /*
  72.  * Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
  73.  * After this, whence is either SEEK_SET or SEEK_END.
  74.  */
  75. switch (whence) {
  76. case SEEK_CUR:
  77. /*
  78.  * In order to seek relative to the current stream offset,
  79.  * we have to first find the current stream offset a la
  80.  * ftell (see ftell for details).
  81.  */
  82. if (fp->_flags & __SOFF)
  83. curoff = fp->_offset;
  84. else {
  85. curoff = __sseek(fp, (off_t)0, SEEK_CUR);
  86. if (curoff == -1L) {
  87. funlockfile(fp);
  88. return (EOF);
  89. }
  90. }
  91. if (fp->_flags & __SRD) {
  92. curoff -= fp->_r;
  93. if (HASUB(fp))
  94. curoff -= fp->_ur;
  95. } else if (fp->_flags & __SWR && fp->_p != NULL)
  96. curoff += fp->_p - fp->_bf._base;
  97. offset += curoff;
  98. whence = SEEK_SET;
  99. havepos = 1;
  100. break;
  101. case SEEK_SET:
  102. case SEEK_END:
  103. curoff = 0; /* XXX just to keep gcc quiet */
  104. havepos = 0;
  105. break;
  106. default:
  107. errno = EINVAL;
  108. funlockfile(fp);
  109. return (EOF);
  110. }
  111. /*
  112.  * Can only optimise if:
  113.  * reading (and not reading-and-writing);
  114.  * not unbuffered; and
  115.  * this is a `regular' Unix file (and hence seekfn==__sseek).
  116.  * We must check __NBF first, because it is possible to have __NBF
  117.  * and __SOPT both set.
  118.  */
  119. if (fp->_bf._base == NULL)
  120. __smakebuf(fp);
  121. if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT))
  122. goto dumb;
  123. if ((fp->_flags & __SOPT) == 0) {
  124. if (fp->_file < 0 || fstat(fp->_file, &st) ||
  125.     (st.st_mode & S_IFMT) != S_IFREG) {
  126. fp->_flags |= __SNPT;
  127. goto dumb;
  128. }
  129. fp->_blksize = st.st_blksize;
  130. fp->_flags |= __SOPT;
  131. }
  132. /*
  133.  * We are reading; we can try to optimise.
  134.  * Figure out where we are going and where we are now.
  135.  */
  136. if (whence == SEEK_SET)
  137. target = offset;
  138. else {
  139. if (fstat(fp->_file, &st))
  140. goto dumb;
  141. target = st.st_size + offset;
  142. }
  143. if (!havepos) {
  144. if (fp->_flags & __SOFF)
  145. curoff = fp->_offset;
  146. else {
  147. curoff = __sseek(fp, (off_t)0, SEEK_CUR);
  148. if (curoff == POS_ERR)
  149. goto dumb;
  150. }
  151. curoff -= fp->_r;
  152. if (HASUB(fp))
  153. curoff -= fp->_ur;
  154. }
  155. /*
  156.  * Compute the number of bytes in the input buffer (pretending
  157.  * that any ungetc() input has been discarded).  Adjust current
  158.  * offset backwards by this count so that it represents the
  159.  * file offset for the first byte in the current input buffer.
  160.  */
  161. if (HASUB(fp)) {
  162. n = fp->_up - fp->_bf._base;
  163. curoff -= n;
  164. n += fp->_ur;
  165. } else {
  166. n = fp->_p - fp->_bf._base;
  167. curoff -= n;
  168. n += fp->_r;
  169. }
  170. /*
  171.  * If the target offset is within the current buffer,
  172.  * simply adjust the pointers, clear EOF, undo ungetc(),
  173.  * and return.  (If the buffer was modified, we have to
  174.  * skip this; see fgetline.c.)
  175.  */
  176. if ((fp->_flags & __SMOD) == 0 &&
  177.     target >= curoff && target < curoff + n) {
  178. register int o = target - curoff;
  179. fp->_p = fp->_bf._base + o;
  180. fp->_r = n - o;
  181. if (HASUB(fp))
  182. FREEUB(fp);
  183. fp->_flags &= ~__SEOF;
  184. funlockfile(fp);
  185. return (0);
  186. }
  187. /*
  188.  * The place we want to get to is not within the current buffer,
  189.  * but we can still be kind to the kernel copyout mechanism.
  190.  * By aligning the file offset to a block boundary, we can let
  191.  * the kernel use the VM hardware to map pages instead of
  192.  * copying bytes laboriously.  Using a block boundary also
  193.  * ensures that we only read one block, rather than two.
  194.  */
  195. curoff = target & ~(fp->_blksize - 1);
  196. if (__sseek(fp, (off_t)curoff, SEEK_SET) != POS_ERR) {
  197. fp->_r = 0;
  198.   fp->_p = fp->_bf._base;
  199. if (HASUB(fp))
  200. FREEUB(fp);
  201. fp->_flags &= ~__SEOF;
  202. n = target - curoff;
  203. if (n) {
  204. if (__srefill(fp) || fp->_r < n)
  205. goto dumb;
  206. fp->_p += n;
  207. fp->_r -= n;
  208. }
  209. funlockfile(fp);
  210. return (0);
  211. }
  212. /*
  213.  * We get here if we cannot optimise the seek ... just
  214.  * do it.  Allow the seek function to change fp->_bf._base.
  215.  */
  216. dumb:
  217. if (__sflush(fp) || __sseek(fp, (off_t)offset, whence) == POS_ERR) {
  218. funlockfile(fp);
  219. return (EOF);
  220. }
  221. /* success: clear EOF indicator and discard ungetc() data */
  222. if (HASUB(fp))
  223. FREEUB(fp);
  224. fp->_p = fp->_bf._base;
  225. fp->_r = 0;
  226. /* fp->_w = 0; */ /* unnecessary (I think...) */
  227. fp->_flags &= ~__SEOF;
  228. funlockfile(fp);
  229. return (0);
  230. }