setvbuf.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. libc_hidden_proto(setvbuf)
  15. int setvbuf(register FILE * __restrict stream, register char * __restrict buf,
  16. int mode, size_t size)
  17. {
  18. #ifdef __STDIO_BUFFERS
  19. int retval = EOF;
  20. int alloc_flag = 0;
  21. __STDIO_AUTO_THREADLOCK_VAR;
  22. __STDIO_AUTO_THREADLOCK(stream);
  23. __STDIO_STREAM_VALIDATE(stream);
  24. if (((unsigned int) mode) > 2) {
  25. __set_errno(EINVAL);
  26. goto ERROR;
  27. }
  28. /* C99 states that setvbuf may only be used between a successful
  29. * open of the stream and before any other operation other than
  30. * an unsuccessful call to setvbuf. */
  31. #ifdef __STDIO_FLEXIBLE_SETVBUF
  32. /* If we aren't currently reading (including ungots) or writing,
  33. * then allow the request to proceed. */
  34. if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING)) {
  35. goto ERROR;
  36. }
  37. #else
  38. /* The following test isn't quite as strict as C99, as it will
  39. * not detect file positioning operations. */
  40. if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING
  41. |__FLAG_NARROW|__FLAG_WIDE
  42. |__FLAG_ERROR|__FLAG_EOF)
  43. ) {
  44. goto ERROR;
  45. }
  46. #endif
  47. stream->__modeflags &= ~(__MASK_BUFMODE); /* Clear current mode */
  48. stream->__modeflags |= mode * __FLAG_LBF; /* and set new one. */
  49. if ((mode == _IONBF) || !size) {
  50. size = 0;
  51. buf = NULL;
  52. } else if (!buf) {
  53. if ((__STDIO_STREAM_BUFFER_SIZE(stream) == size) /* Same size or */
  54. || !(buf = malloc(size)) /* malloc failed, so don't change. */
  55. ) {
  56. goto DONE;
  57. }
  58. alloc_flag = __FLAG_FREEBUF;
  59. }
  60. if (stream->__modeflags & __FLAG_FREEBUF) {
  61. stream->__modeflags &= ~(__FLAG_FREEBUF);
  62. free(stream->__bufstart);
  63. }
  64. stream->__modeflags |= alloc_flag;
  65. stream->__bufstart = buf;
  66. stream->__bufend = buf + size;
  67. __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
  68. __STDIO_STREAM_DISABLE_GETC(stream);
  69. __STDIO_STREAM_DISABLE_PUTC(stream);
  70. DONE:
  71. retval = 0;
  72. ERROR:
  73. __STDIO_STREAM_VALIDATE(stream);
  74. __STDIO_AUTO_THREADUNLOCK(stream);
  75. return retval;
  76. #else /* __STDIO_BUFFERS */
  77. if (mode == _IONBF) {
  78. return 0;
  79. }
  80. if (((unsigned int) mode) > 2) {
  81. __set_errno(EINVAL);
  82. }
  83. return EOF;
  84. #endif
  85. }
  86. libc_hidden_def(setvbuf)