]> sourceware.org Git - glibc.git/blame - stdio/fseek.c
Update to LGPL v2.1.
[glibc.git] / stdio / fseek.c
CommitLineData
c84142e8
UD
1/* Copyright (C) 1991, 92, 93, 95, 96, 97 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
28f540f4 3
c84142e8 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
28f540f4 8
c84142e8
UD
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2
AJ
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
28f540f4 18
28f540f4
RM
19#include <errno.h>
20#include <stdio.h>
21
22
23/* Move the file position of STREAM to OFFSET
24 bytes from the beginning of the file if WHENCE
25 is SEEK_SET, the end of the file is it is SEEK_END,
26 or the current position if it is SEEK_CUR. */
27int
c4029823
UD
28fseek (stream, offset, whence)
29 register FILE *stream;
30 long int offset;
31 int whence;
28f540f4
RM
32{
33 long int o;
34
35 if (!__validfp (stream))
36 {
c4029823 37 __set_errno (EINVAL);
28f540f4
RM
38 return EOF;
39 }
40
41 /* Write out any pending data. */
42 if (stream->__mode.__write && __flshfp (stream, EOF) == EOF)
43 return EOF;
44
45 /* Make sure we know the current offset info. */
747e2b43 46 stream->__offset = -1;
28f540f4
RM
47 if (__stdio_check_offset (stream) == EOF)
48 return EOF;
49
50 /* We are moving the file position, so we are no longer at EOF. */
51 stream->__eof = 0;
52
53 if (stream->__pushed_back)
54 {
55 /* Discard the character pushed back by ungetc. */
56 stream->__bufp = stream->__pushback_bufp;
57 stream->__pushed_back = 0;
58 }
59
60 /* Check the WHENCE argument for validity, and process OFFSET
61 into an absolute position in O. By the end of this switch,
62 either we have returned, or O contains an absolute position. */
63 o = offset;
64 switch (whence)
65 {
66 default:
c4029823 67 __set_errno (EINVAL);
28f540f4
RM
68 return EOF;
69
70 case SEEK_END:
71 /* We don't know where the end of the file is,
72 so seek to the position in the file the user asked
73 for, and then look where that is. */
74 if (stream->__io_funcs.__seek == NULL)
75 {
c4029823 76 __set_errno (ESPIPE);
28f540f4
RM
77 return EOF;
78 }
79 else
80 {
81 fpos_t pos = (fpos_t) o;
82 if ((*stream->__io_funcs.__seek)
83 (stream->__cookie, &pos, SEEK_END) < 0)
84 {
85 if (errno == ESPIPE)
86 stream->__io_funcs.__seek = NULL;
87 return EOF;
88 }
89 stream->__offset = pos;
90 /* Make O be absolute, rather than
91 relative to the end of the file. */
92 o = pos;
93 }
94
95 /* Fall through to try an absolute seek. */
96
97 case SEEK_SET:
98 /* Make O be relative to the buffer. */
99 o -= stream->__target;
100 /* Make O be relative to the current position in the buffer. */
101 o -= stream->__bufp - stream->__buffer;
102
103 /* Fall through to see if we can do it by
104 moving the pointer around in the buffer. */
105
106 case SEEK_CUR:
107 /* If the offset is small enough, we can just
108 move the pointer around in the buffer. */
109
110#if 0 /* Why did I think this would ever work??? */
111 if (stream->__put_limit > stream->__buffer)
112 {
113 /* We are writing. */
114 if (stream->__bufp + o >= stream->__buffer &&
115 stream->__put_limit > stream->__bufp + o &&
116 stream->__get_limit > stream->__bufp + o)
117 {
118 /* We have read all the data we will change soon.
119 We can just move the pointer around. */
120 stream->__bufp += o;
121 return 0;
122 }
123 else
124 {
125 /* Flush the buffer. */
126 if (__flshfp(stream, EOF) == EOF)
127 return EOF;
128 }
129 } else
130#endif
131 if (o < 0 ?
132 (-o <= stream->__bufp - stream->__buffer) :
133 (o <= stream->__get_limit - stream->__bufp))
134 {
135 stream->__bufp += o;
136 return 0;
137 }
138
139 /* Turn it into an absolute seek. */
140 o += stream->__bufp - stream->__buffer;
141 o += stream->__target;
142 break;
143 }
144
145 if (o < 0)
146 {
147 /* Negative file position is meaningless. */
c4029823 148 __set_errno (EINVAL);
28f540f4
RM
149 return -1;
150 }
151
152 /* O is now an absolute position, the new target. */
153 stream->__target = o;
154
155 /* Set bufp and both end pointers to the beginning of the buffer.
156 The next i/o will force a call to the input/output room function. */
157 stream->__bufp
158 = stream->__get_limit = stream->__put_limit = stream->__buffer;
159
160 /* Make sure __flshfp doesn't think the put_limit is at the beginning
161 of the buffer because of line-buffering magic. */
162 stream->__linebuf_active = 0;
163
164 /* If there is no seek function, seeks always fail. */
165 if (stream->__io_funcs.__seek == NULL)
166 {
167 /* This is preemptive, since we don't actually do the seeking.
168 But it makes more sense for fseek to to fail with ESPIPE
169 than for the next reading or writing operation to fail
170 that way. */
c4029823 171 __set_errno (ESPIPE);
28f540f4
RM
172 return EOF;
173 }
174
175 /* Don't actually seek. The next reading or writing operation
176 will force a call to the input or output room function,
177 which will move to the target file position before reading or writing. */
178 return 0;
179}
This page took 0.167395 seconds and 5 git commands to generate.