| /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org> |
| * |
| * GNU Library General Public License (LGPL) version 2 or later. |
| * |
| * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. |
| */ |
| |
| #include "_stdio.h" |
| |
| /* Both ftell() and fseek() (for SEEK_CUR) need to correct the stream's |
| * position to take into account buffered data and ungotten chars. |
| * |
| * If successful, store corrected position in *pos and return >= 0. |
| * Otherwise return < 0. |
| * |
| * If position is unrepresentable, set errno to EOVERFLOW. |
| */ |
| |
| int attribute_hidden __stdio_adjust_position(register FILE * __restrict stream, |
| register __offmax_t *pos) |
| { |
| __offmax_t oldpos; |
| int corr; |
| |
| if ((corr = stream->__modeflags & __MASK_READING) != 0) { |
| --corr; /* Correct for ungots. Assume narrow, and fix below. */ |
| } |
| |
| #ifdef __UCLIBC_HAS_WCHAR__ |
| if (corr && __STDIO_STREAM_IS_WIDE(stream)) { |
| /* A wide stream and we have at least one ungotten wchar. |
| * If it is a user ungot, we need to fail since position |
| * is unspecified as per C99. */ |
| if ((corr > 1) || stream->__ungot[1]) { /* User ungetwc, */ |
| return -1; /* so position is undefined. */ |
| } |
| corr -= (1 + stream->__ungot_width[1]); |
| if (stream->__state.__mask > 0) { /* Incomplete (bad?) mb char. */ |
| corr -= stream->__ungot_width[0]; |
| } |
| } |
| #endif |
| |
| #ifdef __STDIO_BUFFERS |
| corr += (((__STDIO_STREAM_IS_WRITING(stream)) |
| ? stream->__bufstart : stream->__bufread) |
| - stream->__bufpos); |
| #endif |
| |
| oldpos = *pos; |
| |
| /* Range checking cases: |
| * (pos - corr > pos) && (corr > 0) : underflow? return -corr < 0 |
| * (pos - corr > pos) && (corr < 0) : ok .. return -corr > 0 |
| * (pos - corr <= pos) && (corr >= 0) : ok .. return corr > 0 |
| * (pos - corr <= pos) && (corr < 0) : overflow .. return corr < 0 |
| */ |
| |
| if ((*pos -= corr) > oldpos) { |
| corr = -corr; |
| } |
| |
| if (corr < 0) { |
| __set_errno(EOVERFLOW); |
| } |
| |
| return corr; |
| } |