strops.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /* Copyright (C) 1993-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>.
  14. As a special exception, if you link the code in this file with
  15. files compiled with a GNU compiler to produce an executable,
  16. that does not cause the resulting executable to be covered by
  17. the GNU Lesser General Public License. This exception does not
  18. however invalidate any other reasons why the executable file
  19. might be covered by the GNU Lesser General Public License.
  20. This exception applies to code released by its copyright holders
  21. in files containing the exception. */
  22. #include <assert.h>
  23. #include "strfile.h"
  24. #include "libioP.h"
  25. #include <string.h>
  26. #include <stdio_ext.h>
  27. void
  28. _IO_str_init_static_internal (_IO_strfile *sf, char *ptr, size_t size,
  29. char *pstart)
  30. {
  31. FILE *fp = &sf->_sbf._f;
  32. char *end;
  33. if (size == 0)
  34. end = __rawmemchr (ptr, '\0');
  35. else if ((size_t) ptr + size > (size_t) ptr)
  36. end = ptr + size;
  37. else
  38. end = (char *) -1;
  39. _IO_setb (fp, ptr, end, 0);
  40. fp->_IO_write_base = ptr;
  41. fp->_IO_read_base = ptr;
  42. fp->_IO_read_ptr = ptr;
  43. if (pstart)
  44. {
  45. fp->_IO_write_ptr = pstart;
  46. fp->_IO_write_end = end;
  47. fp->_IO_read_end = pstart;
  48. }
  49. else
  50. {
  51. fp->_IO_write_ptr = ptr;
  52. fp->_IO_write_end = ptr;
  53. fp->_IO_read_end = end;
  54. }
  55. /* A null _allocate_buffer function flags the strfile as being static. */
  56. sf->_s._allocate_buffer_unused = (_IO_alloc_type) 0;
  57. }
  58. void
  59. _IO_str_init_static (_IO_strfile *sf, char *ptr, int size, char *pstart)
  60. {
  61. return _IO_str_init_static_internal (sf, ptr, size < 0 ? -1 : size, pstart);
  62. }
  63. void
  64. _IO_str_init_readonly (_IO_strfile *sf, const char *ptr, int size)
  65. {
  66. _IO_str_init_static_internal (sf, (char *) ptr, size < 0 ? -1 : size, NULL);
  67. sf->_sbf._f._flags |= _IO_NO_WRITES;
  68. }
  69. int
  70. _IO_str_overflow (FILE *fp, int c)
  71. {
  72. int flush_only = c == EOF;
  73. size_t pos;
  74. if (fp->_flags & _IO_NO_WRITES)
  75. return flush_only ? 0 : EOF;
  76. if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING))
  77. {
  78. fp->_flags |= _IO_CURRENTLY_PUTTING;
  79. fp->_IO_write_ptr = fp->_IO_read_ptr;
  80. fp->_IO_read_ptr = fp->_IO_read_end;
  81. }
  82. pos = fp->_IO_write_ptr - fp->_IO_write_base;
  83. if (pos >= (size_t) (_IO_blen (fp) + flush_only))
  84. {
  85. if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
  86. return EOF;
  87. else
  88. {
  89. char *new_buf;
  90. char *old_buf = fp->_IO_buf_base;
  91. size_t old_blen = _IO_blen (fp);
  92. size_t new_size = 2 * old_blen + 100;
  93. if (new_size < old_blen)
  94. return EOF;
  95. new_buf = malloc (new_size);
  96. if (new_buf == NULL)
  97. {
  98. /* __ferror(fp) = 1; */
  99. return EOF;
  100. }
  101. if (old_buf)
  102. {
  103. memcpy (new_buf, old_buf, old_blen);
  104. free (old_buf);
  105. /* Make sure _IO_setb won't try to delete _IO_buf_base. */
  106. fp->_IO_buf_base = NULL;
  107. }
  108. memset (new_buf + old_blen, '\0', new_size - old_blen);
  109. _IO_setb (fp, new_buf, new_buf + new_size, 1);
  110. fp->_IO_read_base = new_buf + (fp->_IO_read_base - old_buf);
  111. fp->_IO_read_ptr = new_buf + (fp->_IO_read_ptr - old_buf);
  112. fp->_IO_read_end = new_buf + (fp->_IO_read_end - old_buf);
  113. fp->_IO_write_ptr = new_buf + (fp->_IO_write_ptr - old_buf);
  114. fp->_IO_write_base = new_buf;
  115. fp->_IO_write_end = fp->_IO_buf_end;
  116. }
  117. }
  118. if (!flush_only)
  119. *fp->_IO_write_ptr++ = (unsigned char) c;
  120. if (fp->_IO_write_ptr > fp->_IO_read_end)
  121. fp->_IO_read_end = fp->_IO_write_ptr;
  122. return c;
  123. }
  124. libc_hidden_def (_IO_str_overflow)
  125. int
  126. _IO_str_underflow (FILE *fp)
  127. {
  128. if (fp->_IO_write_ptr > fp->_IO_read_end)
  129. fp->_IO_read_end = fp->_IO_write_ptr;
  130. if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING))
  131. {
  132. fp->_flags &= ~_IO_CURRENTLY_PUTTING;
  133. fp->_IO_read_ptr = fp->_IO_write_ptr;
  134. fp->_IO_write_ptr = fp->_IO_write_end;
  135. }
  136. if (fp->_IO_read_ptr < fp->_IO_read_end)
  137. return *((unsigned char *) fp->_IO_read_ptr);
  138. else
  139. return EOF;
  140. }
  141. libc_hidden_def (_IO_str_underflow)
  142. /* The size of the valid part of the buffer. */
  143. ssize_t
  144. _IO_str_count (FILE *fp)
  145. {
  146. return ((fp->_IO_write_ptr > fp->_IO_read_end
  147. ? fp->_IO_write_ptr : fp->_IO_read_end)
  148. - fp->_IO_read_base);
  149. }
  150. static int
  151. enlarge_userbuf (FILE *fp, off64_t offset, int reading)
  152. {
  153. if ((ssize_t) offset <= _IO_blen (fp))
  154. return 0;
  155. ssize_t oldend = fp->_IO_write_end - fp->_IO_write_base;
  156. /* Try to enlarge the buffer. */
  157. if (fp->_flags & _IO_USER_BUF)
  158. /* User-provided buffer. */
  159. return 1;
  160. size_t newsize = offset + 100;
  161. char *oldbuf = fp->_IO_buf_base;
  162. char *newbuf = malloc (newsize);
  163. if (newbuf == NULL)
  164. return 1;
  165. if (oldbuf != NULL)
  166. {
  167. memcpy (newbuf, oldbuf, _IO_blen (fp));
  168. free (oldbuf);
  169. /* Make sure _IO_setb won't try to delete
  170. _IO_buf_base. */
  171. fp->_IO_buf_base = NULL;
  172. }
  173. _IO_setb (fp, newbuf, newbuf + newsize, 1);
  174. if (reading)
  175. {
  176. fp->_IO_write_base = newbuf + (fp->_IO_write_base - oldbuf);
  177. fp->_IO_write_ptr = newbuf + (fp->_IO_write_ptr - oldbuf);
  178. fp->_IO_write_end = newbuf + (fp->_IO_write_end - oldbuf);
  179. fp->_IO_read_ptr = newbuf + (fp->_IO_read_ptr - oldbuf);
  180. fp->_IO_read_base = newbuf;
  181. fp->_IO_read_end = fp->_IO_buf_end;
  182. }
  183. else
  184. {
  185. fp->_IO_read_base = newbuf + (fp->_IO_read_base - oldbuf);
  186. fp->_IO_read_ptr = newbuf + (fp->_IO_read_ptr - oldbuf);
  187. fp->_IO_read_end = newbuf + (fp->_IO_read_end - oldbuf);
  188. fp->_IO_write_ptr = newbuf + (fp->_IO_write_ptr - oldbuf);
  189. fp->_IO_write_base = newbuf;
  190. fp->_IO_write_end = fp->_IO_buf_end;
  191. }
  192. /* Clear the area between the last write position and th
  193. new position. */
  194. assert (offset >= oldend);
  195. if (reading)
  196. memset (fp->_IO_read_base + oldend, '\0', offset - oldend);
  197. else
  198. memset (fp->_IO_write_base + oldend, '\0', offset - oldend);
  199. return 0;
  200. }
  201. static void
  202. _IO_str_switch_to_get_mode (FILE *fp)
  203. {
  204. if (_IO_in_backup (fp))
  205. fp->_IO_read_base = fp->_IO_backup_base;
  206. else
  207. {
  208. fp->_IO_read_base = fp->_IO_buf_base;
  209. if (fp->_IO_write_ptr > fp->_IO_read_end)
  210. fp->_IO_read_end = fp->_IO_write_ptr;
  211. }
  212. fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_write_ptr;
  213. fp->_flags &= ~_IO_CURRENTLY_PUTTING;
  214. }
  215. off64_t
  216. _IO_str_seekoff (FILE *fp, off64_t offset, int dir, int mode)
  217. {
  218. off64_t new_pos;
  219. if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET))
  220. mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT);
  221. bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
  222. || _IO_in_put_mode (fp));
  223. if (was_writing)
  224. _IO_str_switch_to_get_mode (fp);
  225. if (mode == 0)
  226. {
  227. new_pos = fp->_IO_read_ptr - fp->_IO_read_base;
  228. }
  229. else
  230. {
  231. ssize_t cur_size = _IO_str_count(fp);
  232. new_pos = EOF;
  233. /* Move the get pointer, if requested. */
  234. if (mode & _IOS_INPUT)
  235. {
  236. ssize_t base;
  237. switch (dir)
  238. {
  239. case _IO_seek_set:
  240. base = 0;
  241. break;
  242. case _IO_seek_cur:
  243. base = fp->_IO_read_ptr - fp->_IO_read_base;
  244. break;
  245. default: /* case _IO_seek_end: */
  246. base = cur_size;
  247. break;
  248. }
  249. ssize_t maxval = SSIZE_MAX - base;
  250. if (offset < -base || offset > maxval)
  251. {
  252. __set_errno (EINVAL);
  253. return EOF;
  254. }
  255. base += offset;
  256. if (base > cur_size
  257. && enlarge_userbuf (fp, base, 1) != 0)
  258. return EOF;
  259. fp->_IO_read_ptr = fp->_IO_read_base + base;
  260. fp->_IO_read_end = fp->_IO_read_base + cur_size;
  261. new_pos = base;
  262. }
  263. /* Move the put pointer, if requested. */
  264. if (mode & _IOS_OUTPUT)
  265. {
  266. ssize_t base;
  267. switch (dir)
  268. {
  269. case _IO_seek_set:
  270. base = 0;
  271. break;
  272. case _IO_seek_cur:
  273. base = fp->_IO_write_ptr - fp->_IO_write_base;
  274. break;
  275. default: /* case _IO_seek_end: */
  276. base = cur_size;
  277. break;
  278. }
  279. ssize_t maxval = SSIZE_MAX - base;
  280. if (offset < -base || offset > maxval)
  281. {
  282. __set_errno (EINVAL);
  283. return EOF;
  284. }
  285. base += offset;
  286. if (base > cur_size
  287. && enlarge_userbuf (fp, base, 0) != 0)
  288. return EOF;
  289. fp->_IO_write_ptr = fp->_IO_write_base + base;
  290. new_pos = base;
  291. }
  292. }
  293. return new_pos;
  294. }
  295. libc_hidden_def (_IO_str_seekoff)
  296. int
  297. _IO_str_pbackfail (FILE *fp, int c)
  298. {
  299. if ((fp->_flags & _IO_NO_WRITES) && c != EOF)
  300. return EOF;
  301. return _IO_default_pbackfail (fp, c);
  302. }
  303. libc_hidden_def (_IO_str_pbackfail)
  304. void
  305. _IO_str_finish (FILE *fp, int dummy)
  306. {
  307. if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
  308. free (fp->_IO_buf_base);
  309. fp->_IO_buf_base = NULL;
  310. _IO_default_finish (fp, 0);
  311. }
  312. const struct _IO_jump_t _IO_str_jumps libio_vtable =
  313. {
  314. JUMP_INIT_DUMMY,
  315. JUMP_INIT(finish, _IO_str_finish),
  316. JUMP_INIT(overflow, _IO_str_overflow),
  317. JUMP_INIT(underflow, _IO_str_underflow),
  318. JUMP_INIT(uflow, _IO_default_uflow),
  319. JUMP_INIT(pbackfail, _IO_str_pbackfail),
  320. JUMP_INIT(xsputn, _IO_default_xsputn),
  321. JUMP_INIT(xsgetn, _IO_default_xsgetn),
  322. JUMP_INIT(seekoff, _IO_str_seekoff),
  323. JUMP_INIT(seekpos, _IO_default_seekpos),
  324. JUMP_INIT(setbuf, _IO_default_setbuf),
  325. JUMP_INIT(sync, _IO_default_sync),
  326. JUMP_INIT(doallocate, _IO_default_doallocate),
  327. JUMP_INIT(read, _IO_default_read),
  328. JUMP_INIT(write, _IO_default_write),
  329. JUMP_INIT(seek, _IO_default_seek),
  330. JUMP_INIT(close, _IO_default_close),
  331. JUMP_INIT(stat, _IO_default_stat),
  332. JUMP_INIT(showmanyc, _IO_default_showmanyc),
  333. JUMP_INIT(imbue, _IO_default_imbue)
  334. };