2 * Copyright (c) 1990 The Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * and/or other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 <<fseek>>, <<fseeko>>---set file position
33 int fseek(FILE *<[fp]>, long <[offset]>, int <[whence]>)
34 int fseeko(FILE *<[fp]>, off_t <[offset]>, int <[whence]>)
35 int _fseek_r(struct _reent *<[ptr]>, FILE *<[fp]>,
36 long <[offset]>, int <[whence]>)
37 int _fseeko_r(struct _reent *<[ptr]>, FILE *<[fp]>,
38 off_t <[offset]>, int <[whence]>)
41 Objects of type <<FILE>> can have a ``position'' that records how much
42 of the file your program has already read. Many of the <<stdio>> functions
43 depend on this position, and many change it as a side effect.
45 You can use <<fseek>>/<<fseeko>> to set the position for the file identified by
46 <[fp]>. The value of <[offset]> determines the new position, in one
47 of three ways selected by the value of <[whence]> (defined as macros
50 <<SEEK_SET>>---<[offset]> is the absolute file position (an offset
51 from the beginning of the file) desired. <[offset]> must be positive.
53 <<SEEK_CUR>>---<[offset]> is relative to the current file position.
54 <[offset]> can meaningfully be either positive or negative.
56 <<SEEK_END>>---<[offset]> is relative to the current end of file.
57 <[offset]> can meaningfully be either positive (to increase the size
58 of the file) or negative.
60 See <<ftell>>/<<ftello>> to determine the current file position.
63 <<fseek>>/<<fseeko>> return <<0>> when successful. On failure, the
64 result is <<EOF>>. The reason for failure is indicated in <<errno>>:
65 either <<ESPIPE>> (the stream identified by <[fp]> doesn't support
66 repositioning) or <<EINVAL>> (invalid file position).
69 ANSI C requires <<fseek>>.
71 <<fseeko>> is defined by the Single Unix specification.
73 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
74 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
88 #define POS_ERR (-(_fpos_t)1)
91 * Seek the given file to the given offset.
92 * `Whence' must be one of the three SEEK_* macros.
96 _fseeko_r (struct _reent
*ptr
,
101 _fpos_t (*seekfn
) (struct _reent
*, void *, _fpos_t
, int);
105 #ifdef __USE_INTERNAL_STAT64
112 /* Make sure stdio is set up. */
114 CHECK_INIT (ptr
, fp
);
116 _newlib_flockfile_start (fp
);
118 /* If we've been doing some writing, and we're in append mode
119 then we don't really know where the filepos is. */
121 if (fp
->_flags
& __SAPP
&& fp
->_flags
& __SWR
)
123 /* So flush the buffer and seek to the end. */
127 /* Have to be able to seek. */
129 if ((seekfn
= fp
->_seek
) == NULL
)
131 _REENT_ERRNO(ptr
) = ESPIPE
; /* ??? */
132 _newlib_flockfile_exit (fp
);
137 * Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
138 * After this, whence is either SEEK_SET or SEEK_END.
145 * In order to seek relative to the current stream offset,
146 * we have to first find the current stream offset a la
147 * ftell (see ftell for details).
149 _fflush_r (ptr
, fp
); /* may adjust seek offset on append stream */
150 if (fp
->_flags
& __SOFF
)
151 curoff
= fp
->_offset
;
154 curoff
= seekfn (ptr
, fp
->_cookie
, (_fpos_t
) 0, SEEK_CUR
);
157 _newlib_flockfile_exit (fp
);
161 if (fp
->_flags
& __SRD
)
167 else if (fp
->_flags
& __SWR
&& fp
->_p
!= NULL
)
168 curoff
+= fp
->_p
- fp
->_bf
._base
;
181 _REENT_ERRNO(ptr
) = EINVAL
;
182 _newlib_flockfile_exit (fp
);
187 * Can only optimise if:
188 * reading (and not reading-and-writing);
189 * not unbuffered; and
190 * this is a `regular' Unix file (and hence seekfn==__sseek).
191 * We must check __NBF first, because it is possible to have __NBF
192 * and __SOPT both set.
195 if (fp
->_bf
._base
== NULL
)
196 __smakebuf_r (ptr
, fp
);
198 #ifdef _FSEEK_OPTIMIZATION
199 if (fp
->_flags
& (__SWR
| __SRW
| __SNBF
| __SNPT
))
201 if ((fp
->_flags
& __SOPT
) == 0)
203 if (seekfn
!= __sseek
205 #ifdef __USE_INTERNAL_STAT64
206 || _fstat64_r (ptr
, fp
->_file
, &st
)
208 || _fstat_r (ptr
, fp
->_file
, &st
)
210 || (st
.st_mode
& S_IFMT
) != S_IFREG
)
212 fp
->_flags
|= __SNPT
;
216 fp
->_blksize
= st
.st_blksize
;
220 fp
->_flags
|= __SOPT
;
224 * We are reading; we can try to optimise.
225 * Figure out where we are going and where we are now.
228 if (whence
== SEEK_SET
)
232 #ifdef __USE_INTERNAL_STAT64
233 if (_fstat64_r (ptr
, fp
->_file
, &st
))
235 if (_fstat_r (ptr
, fp
->_file
, &st
))
238 target
= st
.st_size
+ offset
;
243 if (fp
->_flags
& __SOFF
)
244 curoff
= fp
->_offset
;
247 curoff
= seekfn (ptr
, fp
->_cookie
, 0L, SEEK_CUR
);
248 if (curoff
== POS_ERR
)
257 * Compute the number of bytes in the input buffer (pretending
258 * that any ungetc() input has been discarded). Adjust current
259 * offset backwards by this count so that it represents the
260 * file offset for the first byte in the current input buffer.
265 curoff
+= fp
->_r
; /* kill off ungetc */
266 n
= fp
->_up
- fp
->_bf
._base
;
272 n
= fp
->_p
- fp
->_bf
._base
;
278 * If the target offset is within the current buffer,
279 * simply adjust the pointers, clear EOF, undo ungetc(),
283 if (target
>= curoff
&& target
< curoff
+ n
)
285 register int o
= target
- curoff
;
287 fp
->_p
= fp
->_bf
._base
+ o
;
291 fp
->_flags
&= ~__SEOF
;
292 memset (&fp
->_mbstate
, 0, sizeof (_mbstate_t
));
293 _newlib_flockfile_exit (fp
);
298 * The place we want to get to is not within the current buffer,
299 * but we can still be kind to the kernel copyout mechanism.
300 * By aligning the file offset to a block boundary, we can let
301 * the kernel use the VM hardware to map pages instead of
302 * copying bytes laboriously. Using a block boundary also
303 * ensures that we only read one block, rather than two.
306 curoff
= target
& ~(fp
->_blksize
- 1);
307 if (seekfn (ptr
, fp
->_cookie
, curoff
, SEEK_SET
) == POS_ERR
)
310 fp
->_p
= fp
->_bf
._base
;
313 fp
->_flags
&= ~__SEOF
;
317 if (__srefill_r (ptr
, fp
) || fp
->_r
< n
)
322 memset (&fp
->_mbstate
, 0, sizeof (_mbstate_t
));
323 _newlib_flockfile_exit (fp
);
327 * We get here if we cannot optimise the seek ... just
328 * do it. Allow the seek function to change fp->_bf._base.
333 if (_fflush_r (ptr
, fp
)
334 || seekfn (ptr
, fp
->_cookie
, offset
, whence
) == POS_ERR
)
336 _newlib_flockfile_exit (fp
);
339 /* success: clear EOF indicator and discard ungetc() data */
342 fp
->_p
= fp
->_bf
._base
;
344 /* fp->_w = 0; *//* unnecessary (I think...) */
345 fp
->_flags
&= ~__SEOF
;
346 /* Reset no-optimization flag after successful seek. The
347 no-optimization flag may be set in the case of a read
348 stream that is flushed which by POSIX/SUSv3 standards,
349 means that a corresponding seek must not optimize. The
350 optimization is then allowed if no subsequent flush
352 fp
->_flags
&= ~__SNPT
;
353 memset (&fp
->_mbstate
, 0, sizeof (_mbstate_t
));
354 _newlib_flockfile_end (fp
);
361 fseeko (register FILE *fp
,
365 return _fseeko_r (_REENT
, fp
, offset
, whence
);
368 #endif /* !_REENT_ONLY */