1 /* Copyright (C) 1993-2024 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 <https://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. */
31 #include <stdio_ext.h>
34 _IO_str_init_static_internal (_IO_strfile
*sf
, char *ptr
, size_t size
,
37 FILE *fp
= &sf
->_sbf
._f
;
41 end
= strchr (ptr
, '\0');
42 else if ((size_t) ptr
+ size
> (size_t) ptr
)
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
;
53 fp
->_IO_write_ptr
= pstart
;
54 fp
->_IO_write_end
= end
;
55 fp
->_IO_read_end
= pstart
;
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_unused
= (_IO_alloc_type
) 0;
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
);
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
._flags
|= _IO_NO_WRITES
;
81 _IO_str_overflow (FILE *fp
, int c
)
83 int flush_only
= c
== EOF
;
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
>= (size_t) (_IO_blen (fp
) + flush_only
))
96 if (fp
->_flags
& _IO_USER_BUF
) /* not allowed to enlarge */
101 char *old_buf
= fp
->_IO_buf_base
;
102 size_t old_blen
= _IO_blen (fp
);
103 size_t new_size
= 2 * old_blen
+ 100;
104 if (new_size
< old_blen
)
106 new_buf
= malloc (new_size
);
109 /* __ferror(fp) = 1; */
114 memcpy (new_buf
, old_buf
, old_blen
);
116 /* Make sure _IO_setb won't try to delete _IO_buf_base. */
117 fp
->_IO_buf_base
= NULL
;
119 memset (new_buf
+ old_blen
, '\0', new_size
- old_blen
);
121 _IO_setb (fp
, new_buf
, new_buf
+ new_size
, 1);
122 fp
->_IO_read_base
= new_buf
+ (fp
->_IO_read_base
- old_buf
);
123 fp
->_IO_read_ptr
= new_buf
+ (fp
->_IO_read_ptr
- old_buf
);
124 fp
->_IO_read_end
= new_buf
+ (fp
->_IO_read_end
- old_buf
);
125 fp
->_IO_write_ptr
= new_buf
+ (fp
->_IO_write_ptr
- old_buf
);
127 fp
->_IO_write_base
= new_buf
;
128 fp
->_IO_write_end
= fp
->_IO_buf_end
;
133 *fp
->_IO_write_ptr
++ = (unsigned char) c
;
134 if (fp
->_IO_write_ptr
> fp
->_IO_read_end
)
135 fp
->_IO_read_end
= fp
->_IO_write_ptr
;
141 libc_hidden_def (_IO_str_overflow
)
144 _IO_str_underflow (FILE *fp
)
146 if (fp
->_IO_write_ptr
> fp
->_IO_read_end
)
147 fp
->_IO_read_end
= fp
->_IO_write_ptr
;
148 if ((fp
->_flags
& _IO_TIED_PUT_GET
) && (fp
->_flags
& _IO_CURRENTLY_PUTTING
))
150 fp
->_flags
&= ~_IO_CURRENTLY_PUTTING
;
151 fp
->_IO_read_ptr
= fp
->_IO_write_ptr
;
152 fp
->_IO_write_ptr
= fp
->_IO_write_end
;
154 if (fp
->_IO_read_ptr
< fp
->_IO_read_end
)
155 return *((unsigned char *) fp
->_IO_read_ptr
);
159 libc_hidden_def (_IO_str_underflow
)
161 /* The size of the valid part of the buffer. */
164 _IO_str_count (FILE *fp
)
166 return ((fp
->_IO_write_ptr
> fp
->_IO_read_end
167 ? fp
->_IO_write_ptr
: fp
->_IO_read_end
)
168 - fp
->_IO_read_base
);
173 enlarge_userbuf (FILE *fp
, off64_t offset
, int reading
)
175 if ((ssize_t
) offset
<= _IO_blen (fp
))
178 ssize_t oldend
= fp
->_IO_write_end
- fp
->_IO_write_base
;
180 /* Try to enlarge the buffer. */
181 if (fp
->_flags
& _IO_USER_BUF
)
182 /* User-provided buffer. */
185 size_t newsize
= offset
+ 100;
186 char *oldbuf
= fp
->_IO_buf_base
;
187 char *newbuf
= malloc (newsize
);
193 memcpy (newbuf
, oldbuf
, _IO_blen (fp
));
195 /* Make sure _IO_setb won't try to delete
197 fp
->_IO_buf_base
= NULL
;
200 _IO_setb (fp
, newbuf
, newbuf
+ newsize
, 1);
204 fp
->_IO_write_base
= newbuf
+ (fp
->_IO_write_base
- oldbuf
);
205 fp
->_IO_write_ptr
= newbuf
+ (fp
->_IO_write_ptr
- oldbuf
);
206 fp
->_IO_write_end
= newbuf
+ (fp
->_IO_write_end
- oldbuf
);
207 fp
->_IO_read_ptr
= newbuf
+ (fp
->_IO_read_ptr
- oldbuf
);
209 fp
->_IO_read_base
= newbuf
;
210 fp
->_IO_read_end
= fp
->_IO_buf_end
;
214 fp
->_IO_read_base
= newbuf
+ (fp
->_IO_read_base
- oldbuf
);
215 fp
->_IO_read_ptr
= newbuf
+ (fp
->_IO_read_ptr
- oldbuf
);
216 fp
->_IO_read_end
= newbuf
+ (fp
->_IO_read_end
- oldbuf
);
217 fp
->_IO_write_ptr
= newbuf
+ (fp
->_IO_write_ptr
- oldbuf
);
219 fp
->_IO_write_base
= newbuf
;
220 fp
->_IO_write_end
= fp
->_IO_buf_end
;
223 /* Clear the area between the last write position and th
225 assert (offset
>= oldend
);
227 memset (fp
->_IO_read_base
+ oldend
, '\0', offset
- oldend
);
229 memset (fp
->_IO_write_base
+ oldend
, '\0', offset
- oldend
);
235 _IO_str_switch_to_get_mode (FILE *fp
)
237 if (_IO_in_backup (fp
))
238 fp
->_IO_read_base
= fp
->_IO_backup_base
;
241 fp
->_IO_read_base
= fp
->_IO_buf_base
;
242 if (fp
->_IO_write_ptr
> fp
->_IO_read_end
)
243 fp
->_IO_read_end
= fp
->_IO_write_ptr
;
245 fp
->_IO_read_ptr
= fp
->_IO_read_end
= fp
->_IO_write_ptr
;
247 fp
->_flags
&= ~_IO_CURRENTLY_PUTTING
;
251 _IO_str_seekoff (FILE *fp
, off64_t offset
, int dir
, int mode
)
255 if (mode
== 0 && (fp
->_flags
& _IO_TIED_PUT_GET
))
256 mode
= (fp
->_flags
& _IO_CURRENTLY_PUTTING
? _IOS_OUTPUT
: _IOS_INPUT
);
258 bool was_writing
= (fp
->_IO_write_ptr
> fp
->_IO_write_base
259 || _IO_in_put_mode (fp
));
261 _IO_str_switch_to_get_mode (fp
);
265 new_pos
= fp
->_IO_read_ptr
- fp
->_IO_read_base
;
269 ssize_t cur_size
= _IO_str_count(fp
);
272 /* Move the get pointer, if requested. */
273 if (mode
& _IOS_INPUT
)
282 base
= fp
->_IO_read_ptr
- fp
->_IO_read_base
;
284 default: /* case _IO_seek_end: */
288 ssize_t maxval
= SSIZE_MAX
- base
;
289 if (offset
< -base
|| offset
> maxval
)
291 __set_errno (EINVAL
);
296 && enlarge_userbuf (fp
, base
, 1) != 0)
298 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ base
;
299 fp
->_IO_read_end
= fp
->_IO_read_base
+ cur_size
;
303 /* Move the put pointer, if requested. */
304 if (mode
& _IOS_OUTPUT
)
313 base
= fp
->_IO_write_ptr
- fp
->_IO_write_base
;
315 default: /* case _IO_seek_end: */
319 ssize_t maxval
= SSIZE_MAX
- base
;
320 if (offset
< -base
|| offset
> maxval
)
322 __set_errno (EINVAL
);
327 && enlarge_userbuf (fp
, base
, 0) != 0)
329 fp
->_IO_write_ptr
= fp
->_IO_write_base
+ base
;
335 libc_hidden_def (_IO_str_seekoff
)
338 _IO_str_pbackfail (FILE *fp
, int c
)
340 if ((fp
->_flags
& _IO_NO_WRITES
) && c
!= EOF
)
342 return _IO_default_pbackfail (fp
, c
);
344 libc_hidden_def (_IO_str_pbackfail
)
347 _IO_str_finish (FILE *fp
, int dummy
)
349 if (fp
->_IO_buf_base
&& !(fp
->_flags
& _IO_USER_BUF
))
350 free (fp
->_IO_buf_base
);
351 fp
->_IO_buf_base
= NULL
;
353 _IO_default_finish (fp
, 0);