]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/strops.c
2.5-18.1
[thirdparty/glibc.git] / libio / strops.c
CommitLineData
0ecb606c 1/* Copyright (C) 1993, 1997-2003, 2004, 2006 Free Software Foundation, Inc.
41bdb6e2 2 This file is part of the GNU C Library.
96aa2d94 3
41bdb6e2
AJ
4 The GNU C Library is free software; you can redistribute it and/or
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.
96aa2d94 8
41bdb6e2
AJ
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
40a55d20 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2
AJ
12 Lesser General Public License for more details.
13
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.
18
19 As a special exception, if you link the code in this file with
20 files compiled with a GNU compiler to produce an executable,
21 that does not cause the resulting executable to be covered by
22 the GNU Lesser General Public License. This exception does not
23 however invalidate any other reasons why the executable file
24 might be covered by the GNU Lesser General Public License.
25 This exception applies to code released by its copyright holders
26 in files containing the exception. */
96aa2d94 27
0ecb606c 28#include <assert.h>
96aa2d94
RM
29#include "strfile.h"
30#include "libioP.h"
31#include <string.h>
0d875352 32#include <stdio_ext.h>
96aa2d94 33
96aa2d94 34void
40a54e4d 35_IO_str_init_static_internal (sf, ptr, size, pstart)
2ca8b1ee 36 _IO_strfile *sf;
40a55d20 37 char *ptr;
40a54e4d 38 _IO_size_t size;
40a55d20 39 char *pstart;
96aa2d94 40{
2ca8b1ee 41 _IO_FILE *fp = &sf->_sbf._f;
40a54e4d 42 char *end;
2ca8b1ee 43
96aa2d94 44 if (size == 0)
40a54e4d
UD
45 end = __rawmemchr (ptr, '\0');
46 else if ((_IO_size_t) ptr + size > (_IO_size_t) ptr)
47 end = ptr + size;
48 else
49 end = (char *) -1;
50 INTUSE(_IO_setb) (fp, ptr, end, 0);
96aa2d94
RM
51
52 fp->_IO_write_base = ptr;
53 fp->_IO_read_base = ptr;
54 fp->_IO_read_ptr = ptr;
55 if (pstart)
56 {
57 fp->_IO_write_ptr = pstart;
40a54e4d 58 fp->_IO_write_end = end;
96aa2d94
RM
59 fp->_IO_read_end = pstart;
60 }
61 else
62 {
63 fp->_IO_write_ptr = ptr;
64 fp->_IO_write_end = ptr;
40a54e4d 65 fp->_IO_read_end = end;
96aa2d94 66 }
96aa2d94 67 /* A null _allocate_buffer function flags the strfile as being static. */
2ca8b1ee 68 sf->_s._allocate_buffer = (_IO_alloc_type) 0;
96aa2d94 69}
40a54e4d
UD
70
71void
72_IO_str_init_static (sf, ptr, size, pstart)
73 _IO_strfile *sf;
74 char *ptr;
75 int size;
76 char *pstart;
77{
78 return _IO_str_init_static_internal (sf, ptr, size < 0 ? -1 : size, pstart);
79}
96aa2d94
RM
80
81void
2ca8b1ee
GM
82_IO_str_init_readonly (sf, ptr, size)
83 _IO_strfile *sf;
40a55d20
UD
84 const char *ptr;
85 int size;
96aa2d94 86{
40a54e4d 87 _IO_str_init_static_internal (sf, (char *) ptr, size < 0 ? -1 : size, NULL);
2ca8b1ee 88 sf->_sbf._f._IO_file_flags |= _IO_NO_WRITES;
96aa2d94
RM
89}
90
91int
40a55d20
UD
92_IO_str_overflow (fp, c)
93 _IO_FILE *fp;
94 int c;
96aa2d94
RM
95{
96 int flush_only = c == EOF;
8a523922 97 _IO_size_t pos;
96aa2d94
RM
98 if (fp->_flags & _IO_NO_WRITES)
99 return flush_only ? 0 : EOF;
96aa2d94
RM
100 if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
101 {
96aa2d94 102 fp->_flags |= _IO_CURRENTLY_PUTTING;
8a523922
UD
103 fp->_IO_write_ptr = fp->_IO_read_ptr;
104 fp->_IO_read_ptr = fp->_IO_read_end;
96aa2d94 105 }
0ecb606c 106 pos = fp->_IO_write_ptr - fp->_IO_write_base;
40a55d20 107 if (pos >= (_IO_size_t) (_IO_blen (fp) + flush_only))
96aa2d94
RM
108 {
109 if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
8a523922 110 return EOF;
96aa2d94
RM
111 else
112 {
113 char *new_buf;
8a523922 114 char *old_buf = fp->_IO_buf_base;
0ecb606c
JJ
115 size_t old_blen = _IO_blen (fp);
116 _IO_size_t new_size = 2 * old_blen + 100;
117 if (new_size < old_blen)
118 return EOF;
96aa2d94 119 new_buf
40a55d20 120 = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
96aa2d94
RM
121 if (new_buf == NULL)
122 {
123 /* __ferror(fp) = 1; */
124 return EOF;
125 }
d64b6ad0 126 if (old_buf)
96aa2d94 127 {
0ecb606c 128 memcpy (new_buf, old_buf, old_blen);
d64b6ad0 129 (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
96aa2d94
RM
130 /* Make sure _IO_setb won't try to delete _IO_buf_base. */
131 fp->_IO_buf_base = NULL;
132 }
0ecb606c
JJ
133 memset (new_buf + old_blen, '\0', new_size - old_blen);
134
77fe0b9c 135 INTUSE(_IO_setb) (fp, new_buf, new_buf + new_size, 1);
8a523922
UD
136 fp->_IO_read_base = new_buf + (fp->_IO_read_base - old_buf);
137 fp->_IO_read_ptr = new_buf + (fp->_IO_read_ptr - old_buf);
138 fp->_IO_read_end = new_buf + (fp->_IO_read_end - old_buf);
139 fp->_IO_write_ptr = new_buf + (fp->_IO_write_ptr - old_buf);
140
96aa2d94 141 fp->_IO_write_base = new_buf;
f21acc89 142 fp->_IO_write_end = fp->_IO_buf_end;
96aa2d94 143 }
96aa2d94
RM
144 }
145
96aa2d94
RM
146 if (!flush_only)
147 *fp->_IO_write_ptr++ = (unsigned char) c;
8a523922
UD
148 if (fp->_IO_write_ptr > fp->_IO_read_end)
149 fp->_IO_read_end = fp->_IO_write_ptr;
96aa2d94
RM
150 return c;
151}
77fe0b9c 152INTDEF(_IO_str_overflow)
96aa2d94
RM
153
154int
40a55d20
UD
155_IO_str_underflow (fp)
156 _IO_FILE *fp;
96aa2d94 157{
8a523922
UD
158 if (fp->_IO_write_ptr > fp->_IO_read_end)
159 fp->_IO_read_end = fp->_IO_write_ptr;
96aa2d94
RM
160 if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
161 {
162 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
8a523922 163 fp->_IO_read_ptr = fp->_IO_write_ptr;
96aa2d94
RM
164 fp->_IO_write_ptr = fp->_IO_write_end;
165 }
96aa2d94 166 if (fp->_IO_read_ptr < fp->_IO_read_end)
195d0dd4 167 return *((unsigned char *) fp->_IO_read_ptr);
96aa2d94
RM
168 else
169 return EOF;
170}
77fe0b9c 171INTDEF(_IO_str_underflow)
96aa2d94 172
8a523922
UD
173/* The size of the valid part of the buffer. */
174
96aa2d94 175_IO_ssize_t
40a55d20
UD
176_IO_str_count (fp)
177 _IO_FILE *fp;
96aa2d94 178{
2604afb1
UD
179 return ((fp->_IO_write_ptr > fp->_IO_read_end
180 ? fp->_IO_write_ptr : fp->_IO_read_end)
40a55d20 181 - fp->_IO_read_base);
a68b0d31 182}
96aa2d94 183
0ecb606c
JJ
184
185static int
186enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
187{
188 if ((_IO_ssize_t) offset <= _IO_blen (fp))
189 return 0;
190
191 _IO_ssize_t oldend = fp->_IO_write_end - fp->_IO_write_base;
192
193 /* Try to enlarge the buffer. */
194 if (fp->_flags & _IO_USER_BUF)
195 /* User-provided buffer. */
196 return 1;
197
198 _IO_size_t newsize = offset + 100;
199 char *oldbuf = fp->_IO_buf_base;
200 char *newbuf
201 = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize);
202 if (newbuf == NULL)
203 return 1;
204
205 if (oldbuf != NULL)
206 {
207 memcpy (newbuf, oldbuf, _IO_blen (fp));
208 (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
209 /* Make sure _IO_setb won't try to delete
210 _IO_buf_base. */
211 fp->_IO_buf_base = NULL;
212 }
213
214 INTUSE(_IO_setb) (fp, newbuf, newbuf + newsize, 1);
215
216 if (reading)
217 {
218 fp->_IO_write_base = newbuf + (fp->_IO_write_base - oldbuf);
219 fp->_IO_write_ptr = newbuf + (fp->_IO_write_ptr - oldbuf);
220 fp->_IO_write_end = newbuf + (fp->_IO_write_end - oldbuf);
221 fp->_IO_read_ptr = newbuf + (fp->_IO_read_ptr - oldbuf);
222
223 fp->_IO_read_base = newbuf;
224 fp->_IO_read_end = fp->_IO_buf_end;
225 }
226 else
227 {
228 fp->_IO_read_base = newbuf + (fp->_IO_read_base - oldbuf);
229 fp->_IO_read_ptr = newbuf + (fp->_IO_read_ptr - oldbuf);
230 fp->_IO_read_end = newbuf + (fp->_IO_read_end - oldbuf);
231 fp->_IO_write_ptr = newbuf + (fp->_IO_write_ptr - oldbuf);
232
233 fp->_IO_write_base = newbuf;
234 fp->_IO_write_end = fp->_IO_buf_end;
235 }
236
237 /* Clear the area between the last write position and th
238 new position. */
239 assert (offset >= oldend);
240 if (reading)
241 memset (fp->_IO_read_base + oldend, '\0', offset - oldend);
242 else
243 memset (fp->_IO_write_base + oldend, '\0', offset - oldend);
244
245 return 0;
246}
247
248
d64b6ad0 249_IO_off64_t
40a55d20
UD
250_IO_str_seekoff (fp, offset, dir, mode)
251 _IO_FILE *fp;
dfd2257a 252 _IO_off64_t offset;
40a55d20
UD
253 int dir;
254 int mode;
96aa2d94 255{
d64b6ad0 256 _IO_off64_t new_pos;
96aa2d94 257
dd7d45e8
UD
258 if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
259 mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
260
2eb45444 261 if (mode == 0)
96aa2d94 262 {
2eb45444
UD
263 /* Don't move any pointers. But there is no clear indication what
264 mode FP is in. Let's guess. */
265 if (fp->_IO_file_flags & _IO_NO_WRITES)
266 new_pos = fp->_IO_read_ptr - fp->_IO_read_base;
267 else
268 new_pos = fp->_IO_write_ptr - fp->_IO_write_base;
269 }
270 else
271 {
272 _IO_ssize_t cur_size = _IO_str_count(fp);
273 new_pos = EOF;
274
275 /* Move the get pointer, if requested. */
276 if (mode & _IOS_INPUT)
96aa2d94 277 {
2eb45444
UD
278 switch (dir)
279 {
280 case _IO_seek_end:
281 offset += cur_size;
282 break;
283 case _IO_seek_cur:
284 offset += fp->_IO_read_ptr - fp->_IO_read_base;
285 break;
286 default: /* case _IO_seek_set: */
287 break;
288 }
0ecb606c
JJ
289 if (offset < 0)
290 return EOF;
291 if ((_IO_ssize_t) offset > cur_size
292 && enlarge_userbuf (fp, offset, 1) != 0)
2eb45444
UD
293 return EOF;
294 fp->_IO_read_ptr = fp->_IO_read_base + offset;
295 fp->_IO_read_end = fp->_IO_read_base + cur_size;
296 new_pos = offset;
96aa2d94 297 }
96aa2d94 298
2eb45444
UD
299 /* Move the put pointer, if requested. */
300 if (mode & _IOS_OUTPUT)
96aa2d94 301 {
2eb45444
UD
302 switch (dir)
303 {
304 case _IO_seek_end:
305 offset += cur_size;
306 break;
307 case _IO_seek_cur:
308 offset += fp->_IO_write_ptr - fp->_IO_write_base;
309 break;
310 default: /* case _IO_seek_set: */
311 break;
312 }
0ecb606c
JJ
313 if (offset < 0)
314 return EOF;
315 if ((_IO_ssize_t) offset > cur_size
316 && enlarge_userbuf (fp, offset, 0) != 0)
2eb45444
UD
317 return EOF;
318 fp->_IO_write_ptr = fp->_IO_write_base + offset;
319 new_pos = offset;
96aa2d94 320 }
96aa2d94
RM
321 }
322 return new_pos;
323}
77fe0b9c 324INTDEF(_IO_str_seekoff)
96aa2d94
RM
325
326int
40a55d20
UD
327_IO_str_pbackfail (fp, c)
328 _IO_FILE *fp;
329 int c;
96aa2d94
RM
330{
331 if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
332 return EOF;
77fe0b9c 333 return INTUSE(_IO_default_pbackfail) (fp, c);
96aa2d94 334}
77fe0b9c 335INTDEF(_IO_str_pbackfail)
96aa2d94
RM
336
337void
40a55d20
UD
338_IO_str_finish (fp, dummy)
339 _IO_FILE *fp;
340 int dummy;
96aa2d94
RM
341{
342 if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
40a55d20 343 (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
96aa2d94
RM
344 fp->_IO_buf_base = NULL;
345
77fe0b9c 346 INTUSE(_IO_default_finish) (fp, 0);
96aa2d94
RM
347}
348
b2637a22 349const struct _IO_jump_t _IO_str_jumps =
40a55d20 350{
96aa2d94
RM
351 JUMP_INIT_DUMMY,
352 JUMP_INIT(finish, _IO_str_finish),
77fe0b9c
UD
353 JUMP_INIT(overflow, INTUSE(_IO_str_overflow)),
354 JUMP_INIT(underflow, INTUSE(_IO_str_underflow)),
355 JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
356 JUMP_INIT(pbackfail, INTUSE(_IO_str_pbackfail)),
357 JUMP_INIT(xsputn, INTUSE(_IO_default_xsputn)),
358 JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
359 JUMP_INIT(seekoff, INTUSE(_IO_str_seekoff)),
96aa2d94
RM
360 JUMP_INIT(seekpos, _IO_default_seekpos),
361 JUMP_INIT(setbuf, _IO_default_setbuf),
362 JUMP_INIT(sync, _IO_default_sync),
77fe0b9c 363 JUMP_INIT(doallocate, INTUSE(_IO_default_doallocate)),
96aa2d94
RM
364 JUMP_INIT(read, _IO_default_read),
365 JUMP_INIT(write, _IO_default_write),
366 JUMP_INIT(seek, _IO_default_seek),
367 JUMP_INIT(close, _IO_default_close),
dfd2257a
UD
368 JUMP_INIT(stat, _IO_default_stat),
369 JUMP_INIT(showmanyc, _IO_default_showmanyc),
370 JUMP_INIT(imbue, _IO_default_imbue)
96aa2d94 371};