Rev 4874 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
4921 | Serge | 2 | * Copyright (c) 1990 The Regents of the University of California. |
4349 | Serge | 3 | * All rights reserved. |
4 | * |
||
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 | * advertising materials, and 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. |
||
16 | */ |
||
17 | |||
4921 | Serge | 18 | /* |
19 | FUNCTION |
||
20 | < |
||
21 | |||
22 | INDEX |
||
23 | fseek |
||
24 | INDEX |
||
25 | fseeko |
||
26 | INDEX |
||
27 | _fseek_r |
||
28 | INDEX |
||
29 | _fseeko_r |
||
30 | |||
31 | ANSI_SYNOPSIS |
||
32 | #include |
||
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]>) |
||
39 | |||
40 | TRAD_SYNOPSIS |
||
41 | #include |
||
42 | int fseek(<[fp]>, <[offset]>, <[whence]>) |
||
43 | FILE *<[fp]>; |
||
44 | long <[offset]>; |
||
45 | int <[whence]>; |
||
46 | |||
47 | int fseeko(<[fp]>, <[offset]>, <[whence]>) |
||
48 | FILE *<[fp]>; |
||
49 | off_t <[offset]>; |
||
50 | int <[whence]>; |
||
51 | |||
52 | int _fseek_r(<[ptr]>, <[fp]>, <[offset]>, <[whence]>) |
||
53 | struct _reent *<[ptr]>; |
||
54 | FILE *<[fp]>; |
||
55 | long <[offset]>; |
||
56 | int <[whence]>; |
||
57 | |||
58 | int _fseeko_r(<[ptr]>, <[fp]>, <[offset]>, <[whence]>) |
||
59 | struct _reent *<[ptr]>; |
||
60 | FILE *<[fp]>; |
||
61 | off_t <[offset]>; |
||
62 | int <[whence]>; |
||
63 | |||
64 | DESCRIPTION |
||
65 | Objects of type < |
||
66 | of the file your program has already read. Many of the < |
||
67 | depend on this position, and many change it as a side effect. |
||
68 | |||
69 | You can use < |
||
70 | <[fp]>. The value of <[offset]> determines the new position, in one |
||
71 | of three ways selected by the value of <[whence]> (defined as macros |
||
72 | in `< |
||
73 | |||
74 | < |
||
75 | from the beginning of the file) desired. <[offset]> must be positive. |
||
76 | |||
77 | < |
||
78 | <[offset]> can meaningfully be either positive or negative. |
||
79 | |||
80 | < |
||
81 | <[offset]> can meaningfully be either positive (to increase the size |
||
82 | of the file) or negative. |
||
83 | |||
84 | See < |
||
85 | |||
86 | RETURNS |
||
87 | < |
||
88 | result is < |
||
89 | either < |
||
90 | repositioning) or < |
||
91 | |||
92 | PORTABILITY |
||
93 | ANSI C requires < |
||
94 | |||
95 | < |
||
96 | |||
97 | Supporting OS subroutines required: < |
||
98 | < |
||
99 | */ |
||
100 | |||
4349 | Serge | 101 | #include <_ansi.h> |
102 | #include |
||
103 | #include |
||
4921 | Serge | 104 | #include |
105 | #include |
||
106 | #include |
||
107 | #include |
||
108 | #include |
||
109 | #include |
||
110 | #include "local.h" |
||
4349 | Serge | 111 | |
4921 | Serge | 112 | #define POS_ERR (-(_fpos_t)1) |
113 | |||
114 | /* |
||
115 | * Seek the given file to the given offset. |
||
116 | * `Whence' must be one of the three SEEK_* macros. |
||
117 | */ |
||
118 | |||
4349 | Serge | 119 | int |
120 | _DEFUN(_fseeko_r, (ptr, fp, offset, whence), |
||
121 | struct _reent *ptr _AND |
||
122 | register FILE *fp _AND |
||
123 | _off_t offset _AND |
||
124 | int whence) |
||
125 | { |
||
4921 | Serge | 126 | _fpos_t _EXFNPTR(seekfn, (struct _reent *, _PTR, _fpos_t, int)); |
127 | _fpos_t target; |
||
128 | _fpos_t curoff = 0; |
||
129 | size_t n; |
||
130 | #ifdef __USE_INTERNAL_STAT64 |
||
131 | struct stat64 st; |
||
132 | #else |
||
133 | struct stat st; |
||
134 | #endif |
||
135 | int havepos; |
||
136 | |||
137 | /* Make sure stdio is set up. */ |
||
138 | |||
139 | CHECK_INIT (ptr, fp); |
||
140 | |||
141 | _newlib_flockfile_start (fp); |
||
142 | |||
143 | /* If we've been doing some writing, and we're in append mode |
||
144 | then we don't really know where the filepos is. */ |
||
145 | |||
146 | if (fp->_flags & __SAPP && fp->_flags & __SWR) |
||
147 | { |
||
148 | /* So flush the buffer and seek to the end. */ |
||
149 | _fflush_r (ptr, fp); |
||
150 | } |
||
151 | |||
152 | /* Have to be able to seek. */ |
||
153 | |||
154 | if ((seekfn = fp->_seek) == NULL) |
||
155 | { |
||
156 | ptr->_errno = ESPIPE; /* ??? */ |
||
157 | _newlib_flockfile_exit (fp); |
||
158 | return EOF; |
||
159 | } |
||
160 | |||
161 | /* |
||
162 | * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. |
||
163 | * After this, whence is either SEEK_SET or SEEK_END. |
||
164 | */ |
||
165 | |||
166 | switch (whence) |
||
167 | { |
||
168 | case SEEK_CUR: |
||
169 | /* |
||
170 | * In order to seek relative to the current stream offset, |
||
171 | * we have to first find the current stream offset a la |
||
172 | * ftell (see ftell for details). |
||
173 | */ |
||
174 | _fflush_r (ptr, fp); /* may adjust seek offset on append stream */ |
||
175 | if (fp->_flags & __SOFF) |
||
176 | curoff = fp->_offset; |
||
177 | else |
||
178 | { |
||
179 | curoff = seekfn (ptr, fp->_cookie, (_fpos_t) 0, SEEK_CUR); |
||
180 | if (curoff == -1L) |
||
181 | { |
||
182 | _newlib_flockfile_exit (fp); |
||
183 | return EOF; |
||
184 | } |
||
185 | } |
||
186 | if (fp->_flags & __SRD) |
||
187 | { |
||
188 | curoff -= fp->_r; |
||
189 | if (HASUB (fp)) |
||
190 | curoff -= fp->_ur; |
||
191 | } |
||
192 | else if (fp->_flags & __SWR && fp->_p != NULL) |
||
193 | curoff += fp->_p - fp->_bf._base; |
||
194 | |||
195 | offset += curoff; |
||
196 | whence = SEEK_SET; |
||
197 | havepos = 1; |
||
198 | break; |
||
199 | |||
200 | case SEEK_SET: |
||
201 | case SEEK_END: |
||
202 | havepos = 0; |
||
203 | break; |
||
204 | |||
205 | default: |
||
206 | ptr->_errno = EINVAL; |
||
207 | _newlib_flockfile_exit (fp); |
||
208 | return (EOF); |
||
209 | } |
||
210 | |||
211 | /* |
||
212 | * Can only optimise if: |
||
213 | * reading (and not reading-and-writing); |
||
214 | * not unbuffered; and |
||
215 | * this is a `regular' Unix file (and hence seekfn==__sseek). |
||
216 | * We must check __NBF first, because it is possible to have __NBF |
||
217 | * and __SOPT both set. |
||
218 | */ |
||
219 | |||
220 | if (fp->_bf._base == NULL) |
||
221 | __smakebuf_r (ptr, fp); |
||
222 | |||
223 | #ifdef _FSEEK_OPTIMIZATION |
||
224 | if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT)) |
||
225 | goto dumb; |
||
226 | if ((fp->_flags & __SOPT) == 0) |
||
227 | { |
||
228 | if (seekfn != __sseek |
||
229 | || fp->_file < 0 |
||
230 | #ifdef __USE_INTERNAL_STAT64 |
||
231 | || _fstat64_r (ptr, fp->_file, &st) |
||
232 | #else |
||
233 | || _fstat_r (ptr, fp->_file, &st) |
||
234 | #endif |
||
235 | || (st.st_mode & S_IFMT) != S_IFREG) |
||
236 | { |
||
237 | fp->_flags |= __SNPT; |
||
238 | goto dumb; |
||
239 | } |
||
240 | #ifdef HAVE_BLKSIZE |
||
241 | fp->_blksize = st.st_blksize; |
||
242 | #else |
||
243 | fp->_blksize = 1024; |
||
244 | #endif |
||
245 | fp->_flags |= __SOPT; |
||
246 | } |
||
247 | |||
248 | /* |
||
249 | * We are reading; we can try to optimise. |
||
250 | * Figure out where we are going and where we are now. |
||
251 | */ |
||
252 | |||
253 | if (whence == SEEK_SET) |
||
254 | target = offset; |
||
255 | else |
||
256 | { |
||
257 | #ifdef __USE_INTERNAL_STAT64 |
||
258 | if (_fstat64_r (ptr, fp->_file, &st)) |
||
259 | #else |
||
260 | if (_fstat_r (ptr, fp->_file, &st)) |
||
261 | #endif |
||
262 | goto dumb; |
||
263 | target = st.st_size + offset; |
||
264 | } |
||
265 | |||
266 | if (!havepos) |
||
267 | { |
||
268 | if (fp->_flags & __SOFF) |
||
269 | curoff = fp->_offset; |
||
270 | else |
||
271 | { |
||
272 | curoff = seekfn (ptr, fp->_cookie, 0L, SEEK_CUR); |
||
273 | if (curoff == POS_ERR) |
||
274 | goto dumb; |
||
275 | } |
||
276 | curoff -= fp->_r; |
||
277 | if (HASUB (fp)) |
||
278 | curoff -= fp->_ur; |
||
279 | } |
||
280 | |||
281 | /* |
||
282 | * Compute the number of bytes in the input buffer (pretending |
||
283 | * that any ungetc() input has been discarded). Adjust current |
||
284 | * offset backwards by this count so that it represents the |
||
285 | * file offset for the first byte in the current input buffer. |
||
286 | */ |
||
287 | |||
288 | if (HASUB (fp)) |
||
289 | { |
||
290 | curoff += fp->_r; /* kill off ungetc */ |
||
291 | n = fp->_up - fp->_bf._base; |
||
292 | curoff -= n; |
||
293 | n += fp->_ur; |
||
294 | } |
||
295 | else |
||
296 | { |
||
297 | n = fp->_p - fp->_bf._base; |
||
298 | curoff -= n; |
||
299 | n += fp->_r; |
||
300 | } |
||
301 | |||
302 | /* |
||
303 | * If the target offset is within the current buffer, |
||
304 | * simply adjust the pointers, clear EOF, undo ungetc(), |
||
305 | * and return. |
||
306 | */ |
||
307 | |||
308 | if (target >= curoff && target < curoff + n) |
||
309 | { |
||
310 | register int o = target - curoff; |
||
311 | |||
312 | fp->_p = fp->_bf._base + o; |
||
313 | fp->_r = n - o; |
||
314 | if (HASUB (fp)) |
||
315 | FREEUB (ptr, fp); |
||
316 | fp->_flags &= ~__SEOF; |
||
317 | memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); |
||
318 | _newlib_flockfile_exit (fp); |
||
319 | return 0; |
||
320 | } |
||
321 | |||
322 | /* |
||
323 | * The place we want to get to is not within the current buffer, |
||
324 | * but we can still be kind to the kernel copyout mechanism. |
||
325 | * By aligning the file offset to a block boundary, we can let |
||
326 | * the kernel use the VM hardware to map pages instead of |
||
327 | * copying bytes laboriously. Using a block boundary also |
||
328 | * ensures that we only read one block, rather than two. |
||
329 | */ |
||
330 | |||
331 | curoff = target & ~(fp->_blksize - 1); |
||
332 | if (seekfn (ptr, fp->_cookie, curoff, SEEK_SET) == POS_ERR) |
||
333 | goto dumb; |
||
334 | fp->_r = 0; |
||
335 | fp->_p = fp->_bf._base; |
||
336 | if (HASUB (fp)) |
||
337 | FREEUB (ptr, fp); |
||
338 | fp->_flags &= ~__SEOF; |
||
339 | n = target - curoff; |
||
340 | if (n) |
||
341 | { |
||
342 | if (__srefill_r (ptr, fp) || fp->_r < n) |
||
343 | goto dumb; |
||
344 | fp->_p += n; |
||
345 | fp->_r -= n; |
||
346 | } |
||
347 | memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); |
||
348 | _newlib_flockfile_exit (fp); |
||
349 | return 0; |
||
350 | |||
351 | /* |
||
352 | * We get here if we cannot optimise the seek ... just |
||
353 | * do it. Allow the seek function to change fp->_bf._base. |
||
354 | */ |
||
355 | #endif |
||
356 | |||
357 | dumb: |
||
358 | if (_fflush_r (ptr, fp) |
||
359 | || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR) |
||
360 | { |
||
361 | _newlib_flockfile_exit (fp); |
||
362 | return EOF; |
||
363 | } |
||
364 | /* success: clear EOF indicator and discard ungetc() data */ |
||
365 | if (HASUB (fp)) |
||
366 | FREEUB (ptr, fp); |
||
367 | fp->_p = fp->_bf._base; |
||
368 | fp->_r = 0; |
||
369 | /* fp->_w = 0; *//* unnecessary (I think...) */ |
||
370 | fp->_flags &= ~__SEOF; |
||
371 | /* Reset no-optimization flag after successful seek. The |
||
372 | no-optimization flag may be set in the case of a read |
||
373 | stream that is flushed which by POSIX/SUSv3 standards, |
||
374 | means that a corresponding seek must not optimize. The |
||
375 | optimization is then allowed if no subsequent flush |
||
376 | is performed. */ |
||
377 | fp->_flags &= ~__SNPT; |
||
378 | memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); |
||
379 | _newlib_flockfile_end (fp); |
||
380 | return 0; |
||
4349 | Serge | 381 | } |
382 | |||
383 | #ifndef _REENT_ONLY |
||
384 | |||
385 | int |
||
386 | _DEFUN(fseeko, (fp, offset, whence), |
||
387 | register FILE *fp _AND |
||
388 | _off_t offset _AND |
||
389 | int whence) |
||
390 | { |
||
4921 | Serge | 391 | return _fseeko_r (_REENT, fp, offset, whence); |
4349 | Serge | 392 | } |
393 | |||
394 | #endif /* !_REENT_ONLY */>>> |