Add bug 18604 to the correct section
[glibc.git] / libio / strops.c
blobaa5e7002225715626f48984202864943a00f158c
1 /* Copyright (C) 1993-2015 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>.
18 As a special exception, if you link the code in this file with
19 files compiled with a GNU compiler to produce an executable,
20 that does not cause the resulting executable to be covered by
21 the GNU Lesser General Public License. This exception does not
22 however invalidate any other reasons why the executable file
23 might be covered by the GNU Lesser General Public License.
24 This exception applies to code released by its copyright holders
25 in files containing the exception. */
27 #include <assert.h>
28 #include "strfile.h"
29 #include "libioP.h"
30 #include <string.h>
31 #include <stdio_ext.h>
33 void
34 _IO_str_init_static_internal (_IO_strfile *sf, char *ptr, _IO_size_t size,
35 char *pstart)
37 _IO_FILE *fp = &sf->_sbf._f;
38 char *end;
40 if (size == 0)
41 end = __rawmemchr (ptr, '\0');
42 else if ((_IO_size_t) ptr + size > (_IO_size_t) ptr)
43 end = ptr + size;
44 else
45 end = (char *) -1;
46 _IO_setb (fp, ptr, end, 0);
48 fp->_IO_write_base = ptr;
49 fp->_IO_read_base = ptr;
50 fp->_IO_read_ptr = ptr;
51 if (pstart)
53 fp->_IO_write_ptr = pstart;
54 fp->_IO_write_end = end;
55 fp->_IO_read_end = pstart;
57 else
59 fp->_IO_write_ptr = ptr;
60 fp->_IO_write_end = ptr;
61 fp->_IO_read_end = end;
63 /* A null _allocate_buffer function flags the strfile as being static. */
64 sf->_s._allocate_buffer = (_IO_alloc_type) 0;
67 void
68 _IO_str_init_static (_IO_strfile *sf, char *ptr, int size, char *pstart)
70 return _IO_str_init_static_internal (sf, ptr, size < 0 ? -1 : size, pstart);
73 void
74 _IO_str_init_readonly (_IO_strfile *sf, const char *ptr, int size)
76 _IO_str_init_static_internal (sf, (char *) ptr, size < 0 ? -1 : size, NULL);
77 sf->_sbf._f._IO_file_flags |= _IO_NO_WRITES;
80 int
81 _IO_str_overflow (_IO_FILE *fp, int c)
83 int flush_only = c == EOF;
84 _IO_size_t pos;
85 if (fp->_flags & _IO_NO_WRITES)
86 return flush_only ? 0 : EOF;
87 if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
89 fp->_flags |= _IO_CURRENTLY_PUTTING;
90 fp->_IO_write_ptr = fp->_IO_read_ptr;
91 fp->_IO_read_ptr = fp->_IO_read_end;
93 pos = fp->_IO_write_ptr - fp->_IO_write_base;
94 if (pos >= (_IO_size_t) (_IO_blen (fp) + flush_only))
96 if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
97 return EOF;
98 else
100 char *new_buf;
101 char *old_buf = fp->_IO_buf_base;
102 size_t old_blen = _IO_blen (fp);
103 _IO_size_t new_size = 2 * old_blen + 100;
104 if (new_size < old_blen)
105 return EOF;
106 new_buf
107 = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
108 if (new_buf == NULL)
110 /* __ferror(fp) = 1; */
111 return EOF;
113 if (old_buf)
115 memcpy (new_buf, old_buf, old_blen);
116 (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
117 /* Make sure _IO_setb won't try to delete _IO_buf_base. */
118 fp->_IO_buf_base = NULL;
120 memset (new_buf + old_blen, '\0', new_size - old_blen);
122 _IO_setb (fp, new_buf, new_buf + new_size, 1);
123 fp->_IO_read_base = new_buf + (fp->_IO_read_base - old_buf);
124 fp->_IO_read_ptr = new_buf + (fp->_IO_read_ptr - old_buf);
125 fp->_IO_read_end = new_buf + (fp->_IO_read_end - old_buf);
126 fp->_IO_write_ptr = new_buf + (fp->_IO_write_ptr - old_buf);
128 fp->_IO_write_base = new_buf;
129 fp->_IO_write_end = fp->_IO_buf_end;
133 if (!flush_only)
134 *fp->_IO_write_ptr++ = (unsigned char) c;
135 if (fp->_IO_write_ptr > fp->_IO_read_end)
136 fp->_IO_read_end = fp->_IO_write_ptr;
137 return c;
139 libc_hidden_def (_IO_str_overflow)
142 _IO_str_underflow (_IO_FILE *fp)
144 if (fp->_IO_write_ptr > fp->_IO_read_end)
145 fp->_IO_read_end = fp->_IO_write_ptr;
146 if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
148 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
149 fp->_IO_read_ptr = fp->_IO_write_ptr;
150 fp->_IO_write_ptr = fp->_IO_write_end;
152 if (fp->_IO_read_ptr < fp->_IO_read_end)
153 return *((unsigned char *) fp->_IO_read_ptr);
154 else
155 return EOF;
157 libc_hidden_def (_IO_str_underflow)
159 /* The size of the valid part of the buffer. */
161 _IO_ssize_t
162 _IO_str_count (_IO_FILE *fp)
164 return ((fp->_IO_write_ptr > fp->_IO_read_end
165 ? fp->_IO_write_ptr : fp->_IO_read_end)
166 - fp->_IO_read_base);
170 static int
171 enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
173 if ((_IO_ssize_t) offset <= _IO_blen (fp))
174 return 0;
176 _IO_ssize_t oldend = fp->_IO_write_end - fp->_IO_write_base;
178 /* Try to enlarge the buffer. */
179 if (fp->_flags & _IO_USER_BUF)
180 /* User-provided buffer. */
181 return 1;
183 _IO_size_t newsize = offset + 100;
184 char *oldbuf = fp->_IO_buf_base;
185 char *newbuf
186 = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize);
187 if (newbuf == NULL)
188 return 1;
190 if (oldbuf != NULL)
192 memcpy (newbuf, oldbuf, _IO_blen (fp));
193 (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
194 /* Make sure _IO_setb won't try to delete
195 _IO_buf_base. */
196 fp->_IO_buf_base = NULL;
199 _IO_setb (fp, newbuf, newbuf + newsize, 1);
201 if (reading)
203 fp->_IO_write_base = newbuf + (fp->_IO_write_base - oldbuf);
204 fp->_IO_write_ptr = newbuf + (fp->_IO_write_ptr - oldbuf);
205 fp->_IO_write_end = newbuf + (fp->_IO_write_end - oldbuf);
206 fp->_IO_read_ptr = newbuf + (fp->_IO_read_ptr - oldbuf);
208 fp->_IO_read_base = newbuf;
209 fp->_IO_read_end = fp->_IO_buf_end;
211 else
213 fp->_IO_read_base = newbuf + (fp->_IO_read_base - oldbuf);
214 fp->_IO_read_ptr = newbuf + (fp->_IO_read_ptr - oldbuf);
215 fp->_IO_read_end = newbuf + (fp->_IO_read_end - oldbuf);
216 fp->_IO_write_ptr = newbuf + (fp->_IO_write_ptr - oldbuf);
218 fp->_IO_write_base = newbuf;
219 fp->_IO_write_end = fp->_IO_buf_end;
222 /* Clear the area between the last write position and th
223 new position. */
224 assert (offset >= oldend);
225 if (reading)
226 memset (fp->_IO_read_base + oldend, '\0', offset - oldend);
227 else
228 memset (fp->_IO_write_base + oldend, '\0', offset - oldend);
230 return 0;
234 _IO_off64_t
235 _IO_str_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode)
237 _IO_off64_t new_pos;
239 if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
240 mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
242 if (mode == 0)
244 /* Don't move any pointers. But there is no clear indication what
245 mode FP is in. Let's guess. */
246 if (fp->_IO_file_flags & _IO_NO_WRITES)
247 new_pos = fp->_IO_read_ptr - fp->_IO_read_base;
248 else
249 new_pos = fp->_IO_write_ptr - fp->_IO_write_base;
251 else
253 _IO_ssize_t cur_size = _IO_str_count(fp);
254 new_pos = EOF;
256 /* Move the get pointer, if requested. */
257 if (mode & _IOS_INPUT)
259 switch (dir)
261 case _IO_seek_end:
262 offset += cur_size;
263 break;
264 case _IO_seek_cur:
265 offset += fp->_IO_read_ptr - fp->_IO_read_base;
266 break;
267 default: /* case _IO_seek_set: */
268 break;
270 if (offset < 0)
271 return EOF;
272 if ((_IO_ssize_t) offset > cur_size
273 && enlarge_userbuf (fp, offset, 1) != 0)
274 return EOF;
275 fp->_IO_read_ptr = fp->_IO_read_base + offset;
276 fp->_IO_read_end = fp->_IO_read_base + cur_size;
277 new_pos = offset;
280 /* Move the put pointer, if requested. */
281 if (mode & _IOS_OUTPUT)
283 switch (dir)
285 case _IO_seek_end:
286 offset += cur_size;
287 break;
288 case _IO_seek_cur:
289 offset += fp->_IO_write_ptr - fp->_IO_write_base;
290 break;
291 default: /* case _IO_seek_set: */
292 break;
294 if (offset < 0)
295 return EOF;
296 if ((_IO_ssize_t) offset > cur_size
297 && enlarge_userbuf (fp, offset, 0) != 0)
298 return EOF;
299 fp->_IO_write_ptr = fp->_IO_write_base + offset;
300 new_pos = offset;
303 return new_pos;
305 libc_hidden_def (_IO_str_seekoff)
308 _IO_str_pbackfail (_IO_FILE *fp, int c)
310 if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
311 return EOF;
312 return _IO_default_pbackfail (fp, c);
314 libc_hidden_def (_IO_str_pbackfail)
316 void
317 _IO_str_finish (_IO_FILE *fp, int dummy)
319 if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
320 (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
321 fp->_IO_buf_base = NULL;
323 _IO_default_finish (fp, 0);
326 const struct _IO_jump_t _IO_str_jumps =
328 JUMP_INIT_DUMMY,
329 JUMP_INIT(finish, _IO_str_finish),
330 JUMP_INIT(overflow, _IO_str_overflow),
331 JUMP_INIT(underflow, _IO_str_underflow),
332 JUMP_INIT(uflow, _IO_default_uflow),
333 JUMP_INIT(pbackfail, _IO_str_pbackfail),
334 JUMP_INIT(xsputn, _IO_default_xsputn),
335 JUMP_INIT(xsgetn, _IO_default_xsgetn),
336 JUMP_INIT(seekoff, _IO_str_seekoff),
337 JUMP_INIT(seekpos, _IO_default_seekpos),
338 JUMP_INIT(setbuf, _IO_default_setbuf),
339 JUMP_INIT(sync, _IO_default_sync),
340 JUMP_INIT(doallocate, _IO_default_doallocate),
341 JUMP_INIT(read, _IO_default_read),
342 JUMP_INIT(write, _IO_default_write),
343 JUMP_INIT(seek, _IO_default_seek),
344 JUMP_INIT(close, _IO_default_close),
345 JUMP_INIT(stat, _IO_default_stat),
346 JUMP_INIT(showmanyc, _IO_default_showmanyc),
347 JUMP_INIT(imbue, _IO_default_imbue)