setvbuf.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
  2. *
  3. * GNU Library General Public License (LGPL) version 2 or later.
  4. *
  5. * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
  6. */
  7. #include "_stdio.h"
  8. #if (_IOFBF != 0) || (_IOLBF != 1) || (_IONBF != 2)
  9. #error Assumption violated -- values of _IOFBF, _IOLBF, _IONBF
  10. #endif
  11. #if (__FLAG_FBF != 0) || (__FLAG_NBF != (2*__FLAG_LBF))
  12. #error Assumption violated for buffering mode flags
  13. #endif
  14. int attribute_hidden __setvbuf(register FILE * __restrict stream, register char * __restrict buf,
  15. int mode, size_t size)
  16. {
  17. #ifdef __STDIO_BUFFERS
  18. int retval = EOF;
  19. int alloc_flag = 0;
  20. __STDIO_AUTO_THREADLOCK_VAR;
  21. __STDIO_AUTO_THREADLOCK(stream);
  22. __STDIO_STREAM_VALIDATE(stream);
  23. if (((unsigned int) mode) > 2) {
  24. __set_errno(EINVAL);
  25. goto ERROR;
  26. }
  27. /* C99 states that setvbuf may only be used between a successful
  28. * open of the stream and before any other operation other than
  29. * an unsuccessful call to setvbuf. */
  30. #ifdef __STDIO_FLEXIBLE_SETVBUF
  31. /* If we aren't currently reading (including ungots) or writing,
  32. * then allow the request to proceed. */
  33. if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING)) {
  34. goto ERROR;
  35. }
  36. #else
  37. /* The following test isn't quite as strict as C99, as it will
  38. * not detect file positioning operations. */
  39. if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING
  40. |__FLAG_NARROW|__FLAG_WIDE
  41. |__FLAG_ERROR|__FLAG_EOF)
  42. ) {
  43. goto ERROR;
  44. }
  45. #endif
  46. stream->__modeflags &= ~(__MASK_BUFMODE); /* Clear current mode */
  47. stream->__modeflags |= mode * __FLAG_LBF; /* and set new one. */
  48. if ((mode == _IONBF) || !size) {
  49. size = 0;
  50. buf = NULL;
  51. } else if (!buf) {
  52. if ((__STDIO_STREAM_BUFFER_SIZE(stream) == size) /* Same size or */
  53. || !(buf = malloc(size)) /* malloc failed, so don't change. */
  54. ) {
  55. goto DONE;
  56. }
  57. alloc_flag = __FLAG_FREEBUF;
  58. }
  59. if (stream->__modeflags & __FLAG_FREEBUF) {
  60. stream->__modeflags &= ~(__FLAG_FREEBUF);
  61. free(stream->__bufstart);
  62. }
  63. stream->__modeflags |= alloc_flag;
  64. stream->__bufstart = buf;
  65. stream->__bufend = buf + size;
  66. __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
  67. __STDIO_STREAM_DISABLE_GETC(stream);
  68. __STDIO_STREAM_DISABLE_PUTC(stream);
  69. DONE:
  70. retval = 0;
  71. ERROR:
  72. __STDIO_STREAM_VALIDATE(stream);
  73. __STDIO_AUTO_THREADUNLOCK(stream);
  74. return retval;
  75. #else /* __STDIO_BUFFERS */
  76. if (mode == _IONBF) {
  77. return 0;
  78. }
  79. if (((unsigned int) mode) > 2) {
  80. __set_errno(EINVAL);
  81. }
  82. return EOF;
  83. #endif
  84. }
  85. strong_alias(__setvbuf,setvbuf)