]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/strops.c
Update nss tests to new skeleton
[thirdparty/glibc.git] / libio / strops.c
CommitLineData
bfff8b1b 1/* Copyright (C) 1993-2017 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
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>.
41bdb6e2
AJ
17
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. */
96aa2d94 26
107b8a92 27#include <assert.h>
96aa2d94
RM
28#include "strfile.h"
29#include "libioP.h"
30#include <string.h>
0d875352 31#include <stdio_ext.h>
96aa2d94 32
96aa2d94 33void
9dd346ff
JM
34_IO_str_init_static_internal (_IO_strfile *sf, char *ptr, _IO_size_t size,
35 char *pstart)
96aa2d94 36{
2ca8b1ee 37 _IO_FILE *fp = &sf->_sbf._f;
40a54e4d 38 char *end;
2ca8b1ee 39
96aa2d94 40 if (size == 0)
40a54e4d
UD
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;
d18ea0c5 46 _IO_setb (fp, ptr, end, 0);
96aa2d94
RM
47
48 fp->_IO_write_base = ptr;
49 fp->_IO_read_base = ptr;
50 fp->_IO_read_ptr = ptr;
51 if (pstart)
52 {
53 fp->_IO_write_ptr = pstart;
40a54e4d 54 fp->_IO_write_end = end;
96aa2d94
RM
55 fp->_IO_read_end = pstart;
56 }
57 else
58 {
59 fp->_IO_write_ptr = ptr;
60 fp->_IO_write_end = ptr;
40a54e4d 61 fp->_IO_read_end = end;
96aa2d94 62 }
96aa2d94 63 /* A null _allocate_buffer function flags the strfile as being static. */
2ca8b1ee 64 sf->_s._allocate_buffer = (_IO_alloc_type) 0;
96aa2d94 65}
40a54e4d
UD
66
67void
9dd346ff 68_IO_str_init_static (_IO_strfile *sf, char *ptr, int size, char *pstart)
40a54e4d
UD
69{
70 return _IO_str_init_static_internal (sf, ptr, size < 0 ? -1 : size, pstart);
71}
96aa2d94
RM
72
73void
9dd346ff 74_IO_str_init_readonly (_IO_strfile *sf, const char *ptr, int size)
96aa2d94 75{
40a54e4d 76 _IO_str_init_static_internal (sf, (char *) ptr, size < 0 ? -1 : size, NULL);
2ca8b1ee 77 sf->_sbf._f._IO_file_flags |= _IO_NO_WRITES;
96aa2d94
RM
78}
79
80int
9dd346ff 81_IO_str_overflow (_IO_FILE *fp, int c)
96aa2d94
RM
82{
83 int flush_only = c == EOF;
8a523922 84 _IO_size_t pos;
96aa2d94
RM
85 if (fp->_flags & _IO_NO_WRITES)
86 return flush_only ? 0 : EOF;
96aa2d94
RM
87 if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
88 {
96aa2d94 89 fp->_flags |= _IO_CURRENTLY_PUTTING;
8a523922
UD
90 fp->_IO_write_ptr = fp->_IO_read_ptr;
91 fp->_IO_read_ptr = fp->_IO_read_end;
96aa2d94 92 }
107b8a92 93 pos = fp->_IO_write_ptr - fp->_IO_write_base;
40a55d20 94 if (pos >= (_IO_size_t) (_IO_blen (fp) + flush_only))
96aa2d94
RM
95 {
96 if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
8a523922 97 return EOF;
96aa2d94
RM
98 else
99 {
100 char *new_buf;
8a523922 101 char *old_buf = fp->_IO_buf_base;
107b8a92
UD
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;
96aa2d94 106 new_buf
40a55d20 107 = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
96aa2d94
RM
108 if (new_buf == NULL)
109 {
110 /* __ferror(fp) = 1; */
111 return EOF;
112 }
d64b6ad0 113 if (old_buf)
96aa2d94 114 {
107b8a92 115 memcpy (new_buf, old_buf, old_blen);
d64b6ad0 116 (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
96aa2d94
RM
117 /* Make sure _IO_setb won't try to delete _IO_buf_base. */
118 fp->_IO_buf_base = NULL;
119 }
107b8a92
UD
120 memset (new_buf + old_blen, '\0', new_size - old_blen);
121
d18ea0c5 122 _IO_setb (fp, new_buf, new_buf + new_size, 1);
8a523922
UD
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);
127
96aa2d94 128 fp->_IO_write_base = new_buf;
f21acc89 129 fp->_IO_write_end = fp->_IO_buf_end;
96aa2d94 130 }
96aa2d94
RM
131 }
132
96aa2d94
RM
133 if (!flush_only)
134 *fp->_IO_write_ptr++ = (unsigned char) c;
8a523922
UD
135 if (fp->_IO_write_ptr > fp->_IO_read_end)
136 fp->_IO_read_end = fp->_IO_write_ptr;
96aa2d94
RM
137 return c;
138}
d18ea0c5 139libc_hidden_def (_IO_str_overflow)
96aa2d94
RM
140
141int
9dd346ff 142_IO_str_underflow (_IO_FILE *fp)
96aa2d94 143{
8a523922
UD
144 if (fp->_IO_write_ptr > fp->_IO_read_end)
145 fp->_IO_read_end = fp->_IO_write_ptr;
96aa2d94
RM
146 if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
147 {
148 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
8a523922 149 fp->_IO_read_ptr = fp->_IO_write_ptr;
96aa2d94
RM
150 fp->_IO_write_ptr = fp->_IO_write_end;
151 }
96aa2d94 152 if (fp->_IO_read_ptr < fp->_IO_read_end)
195d0dd4 153 return *((unsigned char *) fp->_IO_read_ptr);
96aa2d94 154 else
0923a2c8 155 return EOF;
96aa2d94 156}
d18ea0c5 157libc_hidden_def (_IO_str_underflow)
96aa2d94 158
8a523922
UD
159/* The size of the valid part of the buffer. */
160
96aa2d94 161_IO_ssize_t
9dd346ff 162_IO_str_count (_IO_FILE *fp)
96aa2d94 163{
2604afb1
UD
164 return ((fp->_IO_write_ptr > fp->_IO_read_end
165 ? fp->_IO_write_ptr : fp->_IO_read_end)
40a55d20 166 - fp->_IO_read_base);
a68b0d31 167}
96aa2d94 168
107b8a92
UD
169
170static int
171enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
172{
173 if ((_IO_ssize_t) offset <= _IO_blen (fp))
174 return 0;
175
176 _IO_ssize_t oldend = fp->_IO_write_end - fp->_IO_write_base;
177
178 /* Try to enlarge the buffer. */
179 if (fp->_flags & _IO_USER_BUF)
180 /* User-provided buffer. */
181 return 1;
182
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;
189
190 if (oldbuf != NULL)
191 {
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;
197 }
198
d18ea0c5 199 _IO_setb (fp, newbuf, newbuf + newsize, 1);
107b8a92
UD
200
201 if (reading)
202 {
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);
207
208 fp->_IO_read_base = newbuf;
209 fp->_IO_read_end = fp->_IO_buf_end;
210 }
211 else
212 {
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);
217
218 fp->_IO_write_base = newbuf;
219 fp->_IO_write_end = fp->_IO_buf_end;
220 }
221
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);
229
230 return 0;
231}
232
645f97ce
AZ
233static void
234_IO_str_switch_to_get_mode (_IO_FILE *fp)
235{
236 if (_IO_in_backup (fp))
237 fp->_IO_read_base = fp->_IO_backup_base;
238 else
239 {
240 fp->_IO_read_base = fp->_IO_buf_base;
241 if (fp->_IO_write_ptr > fp->_IO_read_end)
242 fp->_IO_read_end = fp->_IO_write_ptr;
243 }
244 fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_write_ptr;
245
246 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
247}
107b8a92 248
d64b6ad0 249_IO_off64_t
9dd346ff 250_IO_str_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode)
96aa2d94 251{
d64b6ad0 252 _IO_off64_t new_pos;
96aa2d94 253
dd7d45e8
UD
254 if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
255 mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
256
645f97ce
AZ
257 bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
258 || _IO_in_put_mode (fp));
259 if (was_writing)
260 _IO_str_switch_to_get_mode (fp);
261
2eb45444 262 if (mode == 0)
96aa2d94 263 {
645f97ce 264 new_pos = fp->_IO_read_ptr - fp->_IO_read_base;
2eb45444
UD
265 }
266 else
267 {
268 _IO_ssize_t cur_size = _IO_str_count(fp);
269 new_pos = EOF;
270
271 /* Move the get pointer, if requested. */
272 if (mode & _IOS_INPUT)
96aa2d94 273 {
645f97ce 274 _IO_ssize_t base;
2eb45444
UD
275 switch (dir)
276 {
645f97ce
AZ
277 case _IO_seek_set:
278 base = 0;
2eb45444
UD
279 break;
280 case _IO_seek_cur:
645f97ce 281 base = fp->_IO_read_ptr - fp->_IO_read_base;
2eb45444 282 break;
645f97ce
AZ
283 default: /* case _IO_seek_end: */
284 base = cur_size;
2eb45444
UD
285 break;
286 }
645f97ce
AZ
287 _IO_ssize_t maxval = SSIZE_MAX - base;
288 if (offset < -base || offset > maxval)
289 {
290 __set_errno (EINVAL);
291 return EOF;
292 }
293 base += offset;
294 if (base > cur_size
295 && enlarge_userbuf (fp, base, 1) != 0)
2eb45444 296 return EOF;
645f97ce 297 fp->_IO_read_ptr = fp->_IO_read_base + base;
2eb45444 298 fp->_IO_read_end = fp->_IO_read_base + cur_size;
645f97ce 299 new_pos = base;
96aa2d94 300 }
96aa2d94 301
2eb45444
UD
302 /* Move the put pointer, if requested. */
303 if (mode & _IOS_OUTPUT)
96aa2d94 304 {
645f97ce 305 _IO_ssize_t base;
2eb45444
UD
306 switch (dir)
307 {
645f97ce
AZ
308 case _IO_seek_set:
309 base = 0;
2eb45444
UD
310 break;
311 case _IO_seek_cur:
645f97ce 312 base = fp->_IO_write_ptr - fp->_IO_write_base;
2eb45444 313 break;
645f97ce
AZ
314 default: /* case _IO_seek_end: */
315 base = cur_size;
2eb45444
UD
316 break;
317 }
645f97ce
AZ
318 _IO_ssize_t maxval = SSIZE_MAX - base;
319 if (offset < -base || offset > maxval)
320 {
321 __set_errno (EINVAL);
322 return EOF;
323 }
324 base += offset;
325 if (base > cur_size
326 && enlarge_userbuf (fp, base, 0) != 0)
2eb45444 327 return EOF;
645f97ce
AZ
328 fp->_IO_write_ptr = fp->_IO_write_base + base;
329 new_pos = base;
96aa2d94 330 }
96aa2d94
RM
331 }
332 return new_pos;
333}
d18ea0c5 334libc_hidden_def (_IO_str_seekoff)
96aa2d94
RM
335
336int
9dd346ff 337_IO_str_pbackfail (_IO_FILE *fp, int c)
96aa2d94
RM
338{
339 if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
340 return EOF;
d18ea0c5 341 return _IO_default_pbackfail (fp, c);
96aa2d94 342}
d18ea0c5 343libc_hidden_def (_IO_str_pbackfail)
96aa2d94
RM
344
345void
9dd346ff 346_IO_str_finish (_IO_FILE *fp, int dummy)
96aa2d94
RM
347{
348 if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
40a55d20 349 (((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
96aa2d94
RM
350 fp->_IO_buf_base = NULL;
351
d18ea0c5 352 _IO_default_finish (fp, 0);
96aa2d94
RM
353}
354
db3476af 355const struct _IO_jump_t _IO_str_jumps libio_vtable =
40a55d20 356{
96aa2d94
RM
357 JUMP_INIT_DUMMY,
358 JUMP_INIT(finish, _IO_str_finish),
d18ea0c5
AS
359 JUMP_INIT(overflow, _IO_str_overflow),
360 JUMP_INIT(underflow, _IO_str_underflow),
361 JUMP_INIT(uflow, _IO_default_uflow),
362 JUMP_INIT(pbackfail, _IO_str_pbackfail),
363 JUMP_INIT(xsputn, _IO_default_xsputn),
364 JUMP_INIT(xsgetn, _IO_default_xsgetn),
365 JUMP_INIT(seekoff, _IO_str_seekoff),
96aa2d94
RM
366 JUMP_INIT(seekpos, _IO_default_seekpos),
367 JUMP_INIT(setbuf, _IO_default_setbuf),
368 JUMP_INIT(sync, _IO_default_sync),
d18ea0c5 369 JUMP_INIT(doallocate, _IO_default_doallocate),
96aa2d94
RM
370 JUMP_INIT(read, _IO_default_read),
371 JUMP_INIT(write, _IO_default_write),
372 JUMP_INIT(seek, _IO_default_seek),
373 JUMP_INIT(close, _IO_default_close),
dfd2257a
UD
374 JUMP_INIT(stat, _IO_default_stat),
375 JUMP_INIT(showmanyc, _IO_default_showmanyc),
376 JUMP_INIT(imbue, _IO_default_imbue)
96aa2d94 377};