Rev 4874 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4874 | Rev 4921 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* |
1 | /* |
2 | * Copyright (c) 2002, Red Hat Inc. |
2 | * Copyright (c) 1990 The Regents of the University of California. |
3 | * All rights reserved. |
3 | * All rights reserved. |
4 | * |
4 | * |
5 | * Redistribution and use in source and binary forms are permitted |
5 | * Redistribution and use in source and binary forms are permitted |
6 | * provided that the above copyright notice and this paragraph are |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, |
7 | * duplicated in all such forms and that any documentation, |
Line 13... | Line 13... | ||
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
16 | */ |
16 | */ |
Line -... | Line 17... | ||
- | 17 | ||
- | 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 | */ |
|
17 | 100 | ||
18 | #include <_ansi.h> |
101 | #include <_ansi.h> |
19 | #include |
102 | #include |
- | 103 | #include |
|
- | 104 | #include |
|
- | 105 | #include |
|
- | 106 | #include |
|
- | 107 | #include |
|
- | 108 | #include |
|
- | 109 | #include |
|
- | 110 | #include "local.h" |
|
- | 111 | ||
- | 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. |
|
Line 20... | Line 117... | ||
20 | #include |
117 | */ |
21 | 118 | ||
22 | int |
119 | int |
23 | _DEFUN(_fseeko_r, (ptr, fp, offset, whence), |
120 | _DEFUN(_fseeko_r, (ptr, fp, offset, whence), |
24 | struct _reent *ptr _AND |
121 | struct _reent *ptr _AND |
25 | register FILE *fp _AND |
122 | register FILE *fp _AND |
26 | _off_t offset _AND |
123 | _off_t offset _AND |
- | 124 | int whence) |
|
- | 125 | { |
|
- | 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 | ||
27 | int whence) |
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)); |
|
28 | { |
379 | _newlib_flockfile_end (fp); |
Line 29... | Line 380... | ||
29 | return _fseek_r (ptr, fp, (long)offset, whence); |
380 | return 0; |
Line 30... | Line 381... | ||
30 | } |
381 | } |
31 | 382 | ||
32 | #ifndef _REENT_ONLY |
383 | #ifndef _REENT_ONLY |
33 | 384 | ||
34 | int |
385 | int |
35 | _DEFUN(fseeko, (fp, offset, whence), |
386 | _DEFUN(fseeko, (fp, offset, whence), |
36 | register FILE *fp _AND |
- | |
37 | _off_t offset _AND |
387 | register FILE *fp _AND |
38 | int whence) |
388 | _off_t offset _AND |
Line 39... | Line 389... | ||
39 | { |
389 | int whence) |