iofopncook.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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 <libioP.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <shlib-compat.h>
  26. static ssize_t
  27. _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
  28. {
  29. struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
  30. cookie_read_function_t *read_cb = cfile->__io_functions.read;
  31. #ifdef PTR_DEMANGLE
  32. PTR_DEMANGLE (read_cb);
  33. #endif
  34. if (read_cb == NULL)
  35. return -1;
  36. return read_cb (cfile->__cookie, buf, size);
  37. }
  38. static ssize_t
  39. _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
  40. {
  41. struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
  42. cookie_write_function_t *write_cb = cfile->__io_functions.write;
  43. #ifdef PTR_DEMANGLE
  44. PTR_DEMANGLE (write_cb);
  45. #endif
  46. if (write_cb == NULL)
  47. {
  48. fp->_flags |= _IO_ERR_SEEN;
  49. return 0;
  50. }
  51. ssize_t n = write_cb (cfile->__cookie, buf, size);
  52. if (n < size)
  53. fp->_flags |= _IO_ERR_SEEN;
  54. return n;
  55. }
  56. static off64_t
  57. _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
  58. {
  59. struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
  60. cookie_seek_function_t *seek_cb = cfile->__io_functions.seek;
  61. #ifdef PTR_DEMANGLE
  62. PTR_DEMANGLE (seek_cb);
  63. #endif
  64. return ((seek_cb == NULL
  65. || (seek_cb (cfile->__cookie, &offset, dir)
  66. == -1)
  67. || offset == (off64_t) -1)
  68. ? _IO_pos_BAD : offset);
  69. }
  70. static int
  71. _IO_cookie_close (FILE *fp)
  72. {
  73. struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
  74. cookie_close_function_t *close_cb = cfile->__io_functions.close;
  75. #ifdef PTR_DEMANGLE
  76. PTR_DEMANGLE (close_cb);
  77. #endif
  78. if (close_cb == NULL)
  79. return 0;
  80. return close_cb (cfile->__cookie);
  81. }
  82. static off64_t
  83. _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
  84. {
  85. /* We must force the fileops code to always use seek to determine
  86. the position. */
  87. fp->_offset = _IO_pos_BAD;
  88. return _IO_file_seekoff (fp, offset, dir, mode);
  89. }
  90. static const struct _IO_jump_t _IO_cookie_jumps libio_vtable = {
  91. JUMP_INIT_DUMMY,
  92. JUMP_INIT(finish, _IO_file_finish),
  93. JUMP_INIT(overflow, _IO_file_overflow),
  94. JUMP_INIT(underflow, _IO_file_underflow),
  95. JUMP_INIT(uflow, _IO_default_uflow),
  96. JUMP_INIT(pbackfail, _IO_default_pbackfail),
  97. JUMP_INIT(xsputn, _IO_file_xsputn),
  98. JUMP_INIT(xsgetn, _IO_default_xsgetn),
  99. JUMP_INIT(seekoff, _IO_cookie_seekoff),
  100. JUMP_INIT(seekpos, _IO_default_seekpos),
  101. JUMP_INIT(setbuf, _IO_file_setbuf),
  102. JUMP_INIT(sync, _IO_file_sync),
  103. JUMP_INIT(doallocate, _IO_file_doallocate),
  104. JUMP_INIT(read, _IO_cookie_read),
  105. JUMP_INIT(write, _IO_cookie_write),
  106. JUMP_INIT(seek, _IO_cookie_seek),
  107. JUMP_INIT(close, _IO_cookie_close),
  108. JUMP_INIT(stat, _IO_default_stat),
  109. JUMP_INIT(showmanyc, _IO_default_showmanyc),
  110. JUMP_INIT(imbue, _IO_default_imbue),
  111. };
  112. /* Copy the callbacks from SOURCE to *TARGET, with pointer
  113. mangling. */
  114. static void
  115. set_callbacks (cookie_io_functions_t *target,
  116. cookie_io_functions_t source)
  117. {
  118. #ifdef PTR_MANGLE
  119. PTR_MANGLE (source.read);
  120. PTR_MANGLE (source.write);
  121. PTR_MANGLE (source.seek);
  122. PTR_MANGLE (source.close);
  123. #endif
  124. *target = source;
  125. }
  126. void
  127. _IO_cookie_init (struct _IO_cookie_file *cfile, int read_write,
  128. void *cookie, cookie_io_functions_t io_functions)
  129. {
  130. _IO_init_internal (&cfile->__fp.file, 0);
  131. _IO_JUMPS (&cfile->__fp) = &_IO_cookie_jumps;
  132. cfile->__cookie = cookie;
  133. set_callbacks (&cfile->__io_functions, io_functions);
  134. _IO_new_file_init_internal (&cfile->__fp);
  135. _IO_mask_flags (&cfile->__fp.file, read_write,
  136. _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
  137. cfile->__fp.file._flags2 |= _IO_FLAGS2_NEED_LOCK;
  138. /* We use a negative number different from -1 for _fileno to mark that
  139. this special stream is not associated with a real file, but still has
  140. to be treated as such. */
  141. cfile->__fp.file._fileno = -2;
  142. }
  143. FILE *
  144. _IO_fopencookie (void *cookie, const char *mode,
  145. cookie_io_functions_t io_functions)
  146. {
  147. int read_write;
  148. struct locked_FILE
  149. {
  150. struct _IO_cookie_file cfile;
  151. #ifdef _IO_MTSAFE_IO
  152. _IO_lock_t lock;
  153. #endif
  154. } *new_f;
  155. switch (*mode++)
  156. {
  157. case 'r':
  158. read_write = _IO_NO_WRITES;
  159. break;
  160. case 'w':
  161. read_write = _IO_NO_READS;
  162. break;
  163. case 'a':
  164. read_write = _IO_NO_READS|_IO_IS_APPENDING;
  165. break;
  166. default:
  167. __set_errno (EINVAL);
  168. return NULL;
  169. }
  170. if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+'))
  171. read_write &= _IO_IS_APPENDING;
  172. new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
  173. if (new_f == NULL)
  174. return NULL;
  175. #ifdef _IO_MTSAFE_IO
  176. new_f->cfile.__fp.file._lock = &new_f->lock;
  177. #endif
  178. _IO_cookie_init (&new_f->cfile, read_write, cookie, io_functions);
  179. return (FILE *) &new_f->cfile.__fp;
  180. }
  181. versioned_symbol (libc, _IO_fopencookie, fopencookie, GLIBC_2_2);
  182. #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
  183. static off64_t
  184. attribute_compat_text_section
  185. _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
  186. {
  187. struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
  188. int (*seek_cb) (FILE *, off_t, int)
  189. = (int (*) (FILE *, off_t, int)) cfile->__io_functions.seek;
  190. #ifdef PTR_DEMANGLE
  191. PTR_DEMANGLE (seek_cb);
  192. #endif
  193. if (seek_cb == NULL)
  194. return _IO_pos_BAD;
  195. int ret = seek_cb (cfile->__cookie, offset, dir);
  196. return (ret == -1) ? _IO_pos_BAD : ret;
  197. }
  198. static const struct _IO_jump_t _IO_old_cookie_jumps libio_vtable = {
  199. JUMP_INIT_DUMMY,
  200. JUMP_INIT(finish, _IO_file_finish),
  201. JUMP_INIT(overflow, _IO_file_overflow),
  202. JUMP_INIT(underflow, _IO_file_underflow),
  203. JUMP_INIT(uflow, _IO_default_uflow),
  204. JUMP_INIT(pbackfail, _IO_default_pbackfail),
  205. JUMP_INIT(xsputn, _IO_file_xsputn),
  206. JUMP_INIT(xsgetn, _IO_default_xsgetn),
  207. JUMP_INIT(seekoff, _IO_cookie_seekoff),
  208. JUMP_INIT(seekpos, _IO_default_seekpos),
  209. JUMP_INIT(setbuf, _IO_file_setbuf),
  210. JUMP_INIT(sync, _IO_file_sync),
  211. JUMP_INIT(doallocate, _IO_file_doallocate),
  212. JUMP_INIT(read, _IO_cookie_read),
  213. JUMP_INIT(write, _IO_cookie_write),
  214. JUMP_INIT(seek, _IO_old_cookie_seek),
  215. JUMP_INIT(close, _IO_cookie_close),
  216. JUMP_INIT(stat, _IO_default_stat),
  217. JUMP_INIT(showmanyc, _IO_default_showmanyc),
  218. JUMP_INIT(imbue, _IO_default_imbue),
  219. };
  220. FILE *
  221. attribute_compat_text_section
  222. _IO_old_fopencookie (void *cookie, const char *mode,
  223. cookie_io_functions_t io_functions)
  224. {
  225. FILE *ret;
  226. ret = _IO_fopencookie (cookie, mode, io_functions);
  227. if (ret != NULL)
  228. _IO_JUMPS_FILE_plus (ret) = &_IO_old_cookie_jumps;
  229. return ret;
  230. }
  231. compat_symbol (libc, _IO_old_fopencookie, fopencookie, GLIBC_2_0);
  232. #endif