blob: bc6e905559126322b8997234404c912397ae98e1 [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
2 *
3 * GNU Library General Public License (LGPL) version 2 or later.
4 *
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
6 */
7
8#include "_stdio.h"
9
10/* Both ftell() and fseek() (for SEEK_CUR) need to correct the stream's
11 * position to take into account buffered data and ungotten chars.
12 *
13 * If successful, store corrected position in *pos and return >= 0.
14 * Otherwise return < 0.
15 *
16 * If position is unrepresentable, set errno to EOVERFLOW.
17 */
18
19int attribute_hidden __stdio_adjust_position(register FILE * __restrict stream,
20 register __offmax_t *pos)
21{
22 __offmax_t oldpos;
23 int corr;
24
25 if ((corr = stream->__modeflags & __MASK_READING) != 0) {
26 --corr; /* Correct for ungots. Assume narrow, and fix below. */
27 }
28
29#ifdef __UCLIBC_HAS_WCHAR__
30 if (corr && __STDIO_STREAM_IS_WIDE(stream)) {
31 /* A wide stream and we have at least one ungotten wchar.
32 * If it is a user ungot, we need to fail since position
33 * is unspecified as per C99. */
34 if ((corr > 1) || stream->__ungot[1]) { /* User ungetwc, */
35 return -1; /* so position is undefined. */
36 }
37 corr -= (1 + stream->__ungot_width[1]);
38 if (stream->__state.__mask > 0) { /* Incomplete (bad?) mb char. */
39 corr -= stream->__ungot_width[0];
40 }
41 }
42#endif
43
44#ifdef __STDIO_BUFFERS
45 corr += (((__STDIO_STREAM_IS_WRITING(stream))
46 ? stream->__bufstart : stream->__bufread)
47 - stream->__bufpos);
48#endif
49
50 oldpos = *pos;
51
52 /* Range checking cases:
53 * (pos - corr > pos) && (corr > 0) : underflow? return -corr < 0
54 * (pos - corr > pos) && (corr < 0) : ok .. return -corr > 0
55 * (pos - corr <= pos) && (corr >= 0) : ok .. return corr > 0
56 * (pos - corr <= pos) && (corr < 0) : overflow .. return corr < 0
57 */
58
59 if ((*pos -= corr) > oldpos) {
60 corr = -corr;
61 }
62
63 if (corr < 0) {
64 __set_errno(EOVERFLOW);
65 }
66
67 return corr;
68}