fseek.c (82348) | fseek.c (82588) |
---|---|
1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Chris Torek. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 25 unchanged lines hidden (view full) --- 34 * SUCH DAMAGE. 35 */ 36 37#if defined(LIBC_SCCS) && !defined(lint) 38#if 0 39static char sccsid[] = "@(#)fseek.c 8.3 (Berkeley) 1/2/94"; 40#endif 41static const char rcsid[] = | 1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Chris Torek. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 25 unchanged lines hidden (view full) --- 34 * SUCH DAMAGE. 35 */ 36 37#if defined(LIBC_SCCS) && !defined(lint) 38#if 0 39static char sccsid[] = "@(#)fseek.c 8.3 (Berkeley) 1/2/94"; 40#endif 41static const char rcsid[] = |
42 "$FreeBSD: head/lib/libc/stdio/fseek.c 82348 2001-08-26 10:38:29Z ache $"; | 42 "$FreeBSD: head/lib/libc/stdio/fseek.c 82588 2001-08-30 19:54:04Z ache $"; |
43#endif /* LIBC_SCCS and not lint */ 44 45#include "namespace.h" 46#include <sys/types.h> 47#include <sys/stat.h> 48#include <errno.h> 49#include <fcntl.h> 50#include <limits.h> --- 58 unchanged lines hidden (view full) --- 109 struct stat st; 110 int havepos; 111 112 /* 113 * Have to be able to seek. 114 */ 115 if ((seekfn = fp->_seek) == NULL) { 116 errno = ESPIPE; /* historic practice */ | 43#endif /* LIBC_SCCS and not lint */ 44 45#include "namespace.h" 46#include <sys/types.h> 47#include <sys/stat.h> 48#include <errno.h> 49#include <fcntl.h> 50#include <limits.h> --- 58 unchanged lines hidden (view full) --- 109 struct stat st; 110 int havepos; 111 112 /* 113 * Have to be able to seek. 114 */ 115 if ((seekfn = fp->_seek) == NULL) { 116 errno = ESPIPE; /* historic practice */ |
117 return (EOF); | 117 return (-1); |
118 } 119 120 /* 121 * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. 122 * After this, whence is either SEEK_SET or SEEK_END. 123 */ 124 switch (whence) { 125 126 case SEEK_CUR: 127 /* 128 * In order to seek relative to the current stream offset, 129 * we have to first find the current stream offset a la 130 * ftell (see ftell for details). 131 */ 132 if (fp->_flags & __SOFF) 133 curoff = fp->_offset; 134 else { 135 curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR); 136 if (curoff == -1) | 118 } 119 120 /* 121 * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. 122 * After this, whence is either SEEK_SET or SEEK_END. 123 */ 124 switch (whence) { 125 126 case SEEK_CUR: 127 /* 128 * In order to seek relative to the current stream offset, 129 * we have to first find the current stream offset a la 130 * ftell (see ftell for details). 131 */ 132 if (fp->_flags & __SOFF) 133 curoff = fp->_offset; 134 else { 135 curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR); 136 if (curoff == -1) |
137 return (EOF); | 137 return (-1); |
138 } 139 if (fp->_flags & __SRD) { 140 curoff -= fp->_r; | 138 } 139 if (fp->_flags & __SRD) { 140 curoff -= fp->_r; |
141 if (HASUB(fp)) | 141 if (curoff < 0) { 142 if (HASUB(fp)) { 143 fp->_p -= curoff; 144 fp->_r += curoff; 145 curoff = 0; 146 } else { 147 errno = EBADF; 148 return (-1); 149 } 150 } 151 if (HASUB(fp)) { |
142 curoff -= fp->_ur; | 152 curoff -= fp->_ur; |
143 } else if (fp->_flags & __SWR && fp->_p != NULL) 144 curoff += fp->_p - fp->_bf._base; 145 | 153 if (curoff < 0) { 154 errno = EBADF; 155 return (-1); 156 } 157 } 158 } else if ((fp->_flags & __SWR) && fp->_p != NULL) { 159 n = fp->_p - fp->_bf._base; 160 if (curoff > OFF_MAX - n) { 161 errno = EOVERFLOW; 162 return (-1); 163 } 164 curoff += n; 165 } |
146 if (offset > 0 && curoff > OFF_MAX - offset) { 147 errno = EOVERFLOW; | 166 if (offset > 0 && curoff > OFF_MAX - offset) { 167 errno = EOVERFLOW; |
148 return (EOF); | 168 return (-1); |
149 } 150 offset += curoff; | 169 } 170 offset += curoff; |
151 /* Disallow negative seeks per POSIX */ | |
152 if (offset < 0) { 153 errno = EINVAL; | 171 if (offset < 0) { 172 errno = EINVAL; |
154 return (EOF); | 173 return (-1); |
155 } 156 if (ltest && offset > LONG_MAX) { 157 errno = EOVERFLOW; | 174 } 175 if (ltest && offset > LONG_MAX) { 176 errno = EOVERFLOW; |
158 return (EOF); | 177 return (-1); |
159 } 160 whence = SEEK_SET; 161 havepos = 1; 162 break; 163 164 case SEEK_SET: | 178 } 179 whence = SEEK_SET; 180 havepos = 1; 181 break; 182 183 case SEEK_SET: |
165 /* Disallow negative seeks per POSIX */ | |
166 if (offset < 0) { 167 errno = EINVAL; | 184 if (offset < 0) { 185 errno = EINVAL; |
168 return (EOF); | 186 return (-1); |
169 } 170 case SEEK_END: 171 curoff = 0; /* XXX just to keep gcc quiet */ 172 havepos = 0; 173 break; 174 175 default: 176 errno = EINVAL; | 187 } 188 case SEEK_END: 189 curoff = 0; /* XXX just to keep gcc quiet */ 190 havepos = 0; 191 break; 192 193 default: 194 errno = EINVAL; |
177 return (EOF); | 195 return (-1); |
178 } 179 180 /* 181 * Can only optimise if: 182 * reading (and not reading-and-writing); 183 * not unbuffered; and 184 * this is a `regular' Unix file (and hence seekfn==__sseek). 185 * We must check __NBF first, because it is possible to have __NBF --- 20 unchanged lines hidden (view full) --- 206 */ 207 if (whence == SEEK_SET) 208 target = offset; 209 else { 210 if (_fstat(fp->_file, &st)) 211 goto dumb; 212 if (offset > 0 && st.st_size > OFF_MAX - offset) { 213 errno = EOVERFLOW; | 196 } 197 198 /* 199 * Can only optimise if: 200 * reading (and not reading-and-writing); 201 * not unbuffered; and 202 * this is a `regular' Unix file (and hence seekfn==__sseek). 203 * We must check __NBF first, because it is possible to have __NBF --- 20 unchanged lines hidden (view full) --- 224 */ 225 if (whence == SEEK_SET) 226 target = offset; 227 else { 228 if (_fstat(fp->_file, &st)) 229 goto dumb; 230 if (offset > 0 && st.st_size > OFF_MAX - offset) { 231 errno = EOVERFLOW; |
214 return (EOF); | 232 return (-1); |
215 } 216 target = st.st_size + offset; | 233 } 234 target = st.st_size + offset; |
217 /* Disallow negative seeks per POSIX */ | |
218 if ((off_t)target < 0) { 219 errno = EINVAL; | 235 if ((off_t)target < 0) { 236 errno = EINVAL; |
220 return (EOF); | 237 return (-1); |
221 } 222 if (ltest && (off_t)target > LONG_MAX) { 223 errno = EOVERFLOW; | 238 } 239 if (ltest && (off_t)target > LONG_MAX) { 240 errno = EOVERFLOW; |
224 return (EOF); | 241 return (-1); |
225 } 226 } 227 228 if (!havepos) { 229 if (fp->_flags & __SOFF) 230 curoff = fp->_offset; 231 else { 232 curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR); 233 if (curoff == POS_ERR) 234 goto dumb; 235 } 236 curoff -= fp->_r; | 242 } 243 } 244 245 if (!havepos) { 246 if (fp->_flags & __SOFF) 247 curoff = fp->_offset; 248 else { 249 curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR); 250 if (curoff == POS_ERR) 251 goto dumb; 252 } 253 curoff -= fp->_r; |
237 if (HASUB(fp)) | 254 if (curoff < 0) { 255 if (HASUB(fp)) { 256 fp->_p -= curoff; 257 fp->_r += curoff; 258 curoff = 0; 259 } else { 260 errno = EBADF; 261 return (-1); 262 } 263 } 264 if (HASUB(fp)) { |
238 curoff -= fp->_ur; | 265 curoff -= fp->_ur; |
266 if (curoff < 0) { 267 errno = EBADF; 268 return (-1); 269 } 270 } |
|
239 } 240 241 /* 242 * Compute the number of bytes in the input buffer (pretending 243 * that any ungetc() input has been discarded). Adjust current 244 * offset backwards by this count so that it represents the 245 * file offset for the first byte in the current input buffer. 246 */ 247 if (HASUB(fp)) { | 271 } 272 273 /* 274 * Compute the number of bytes in the input buffer (pretending 275 * that any ungetc() input has been discarded). Adjust current 276 * offset backwards by this count so that it represents the 277 * file offset for the first byte in the current input buffer. 278 */ 279 if (HASUB(fp)) { |
280 if (curoff > OFF_MAX - fp->_r) 281 goto abspos; |
|
248 curoff += fp->_r; /* kill off ungetc */ 249 n = fp->_extra->_up - fp->_bf._base; 250 curoff -= n; 251 n += fp->_ur; 252 } else { 253 n = fp->_p - fp->_bf._base; 254 curoff -= n; 255 n += fp->_r; 256 } | 282 curoff += fp->_r; /* kill off ungetc */ 283 n = fp->_extra->_up - fp->_bf._base; 284 curoff -= n; 285 n += fp->_ur; 286 } else { 287 n = fp->_p - fp->_bf._base; 288 curoff -= n; 289 n += fp->_r; 290 } |
291 /* curoff can be negative at this point. */ |
|
257 258 /* 259 * If the target offset is within the current buffer, 260 * simply adjust the pointers, clear EOF, undo ungetc(), 261 * and return. (If the buffer was modified, we have to 262 * skip this; see fgetln.c.) 263 */ 264 if ((fp->_flags & __SMOD) == 0 && | 292 293 /* 294 * If the target offset is within the current buffer, 295 * simply adjust the pointers, clear EOF, undo ungetc(), 296 * and return. (If the buffer was modified, we have to 297 * skip this; see fgetln.c.) 298 */ 299 if ((fp->_flags & __SMOD) == 0 && |
265 target >= curoff && target < curoff + n) { 266 register int o = target - curoff; | 300 target >= curoff && 301 (curoff <= 0 || curoff <= OFF_MAX - n) && 302 target < curoff + n) { 303 size_t o = target - curoff; |
267 268 fp->_p = fp->_bf._base + o; 269 fp->_r = n - o; 270 if (HASUB(fp)) 271 FREEUB(fp); 272 fp->_flags &= ~__SEOF; 273 return (0); 274 } 275 | 304 305 fp->_p = fp->_bf._base + o; 306 fp->_r = n - o; 307 if (HASUB(fp)) 308 FREEUB(fp); 309 fp->_flags &= ~__SEOF; 310 return (0); 311 } 312 |
313abspos: |
|
276 /* 277 * The place we want to get to is not within the current buffer, 278 * but we can still be kind to the kernel copyout mechanism. 279 * By aligning the file offset to a block boundary, we can let 280 * the kernel use the VM hardware to map pages instead of 281 * copying bytes laboriously. Using a block boundary also 282 * ensures that we only read one block, rather than two. 283 */ --- 16 unchanged lines hidden (view full) --- 300 301 /* 302 * We get here if we cannot optimise the seek ... just 303 * do it. Allow the seek function to change fp->_bf._base. 304 */ 305dumb: 306 if (__sflush(fp) || 307 (*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) | 314 /* 315 * The place we want to get to is not within the current buffer, 316 * but we can still be kind to the kernel copyout mechanism. 317 * By aligning the file offset to a block boundary, we can let 318 * the kernel use the VM hardware to map pages instead of 319 * copying bytes laboriously. Using a block boundary also 320 * ensures that we only read one block, rather than two. 321 */ --- 16 unchanged lines hidden (view full) --- 338 339 /* 340 * We get here if we cannot optimise the seek ... just 341 * do it. Allow the seek function to change fp->_bf._base. 342 */ 343dumb: 344 if (__sflush(fp) || 345 (*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) |
308 return (EOF); 309 /* POSIX require long type resulting offset for fseek() */ 310 if (ltest && fp->_offset != (long)fp->_offset) { | 346 return (-1); 347 if (ltest && fp->_offset > LONG_MAX) { |
311 errno = EOVERFLOW; | 348 errno = EOVERFLOW; |
312 return (EOF); | 349 return (-1); |
313 } 314 /* success: clear EOF indicator and discard ungetc() data */ 315 if (HASUB(fp)) 316 FREEUB(fp); 317 fp->_p = fp->_bf._base; 318 fp->_r = 0; 319 /* fp->_w = 0; */ /* unnecessary (I think...) */ 320 fp->_flags &= ~__SEOF; 321 return (0); 322} | 350 } 351 /* success: clear EOF indicator and discard ungetc() data */ 352 if (HASUB(fp)) 353 FREEUB(fp); 354 fp->_p = fp->_bf._base; 355 fp->_r = 0; 356 /* fp->_w = 0; */ /* unnecessary (I think...) */ 357 fp->_flags &= ~__SEOF; 358 return (0); 359} |