_trans2w.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. /* Function to handle transition to writing.
  9. * Initialize or verify the stream's orientation (even if readonly).
  10. * Check that the stream is writable.
  11. * If currently reading, check that we can transition to writing.
  12. * C99 requires that the stream is at EOF, but attempting to
  13. * auto-transition via fseek() is a configurable option.
  14. * Returns 0 on success and EOF otherwise.
  15. *
  16. * Notes:
  17. * There are two function signatures, depending on wchar support,
  18. * since with no wchar support the orientation is narrow by default.
  19. */
  20. #ifdef __UCLIBC_HAS_WCHAR__
  21. int attribute_hidden __stdio_trans2w_o(FILE * __restrict stream, int oflag)
  22. #else
  23. int attribute_hidden __stdio_trans2w(FILE * __restrict stream)
  24. #endif
  25. {
  26. __STDIO_STREAM_VALIDATE(stream);
  27. assert(!__STDIO_STREAM_IS_WRITING(stream));
  28. #ifdef __UCLIBC_HAS_WCHAR__
  29. if (!(stream->__modeflags & oflag)) {
  30. if (stream->__modeflags & (__FLAG_NARROW|__FLAG_WIDE)) {
  31. __UNDEFINED_OR_NONPORTABLE;
  32. goto DO_EBADF;
  33. }
  34. stream->__modeflags |= oflag;
  35. }
  36. #endif
  37. if (stream->__modeflags & __FLAG_READONLY) {
  38. #if defined(__UCLIBC_HAS_WCHAR__) || !defined(__UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__)
  39. DO_EBADF:
  40. #endif
  41. __set_errno(EBADF);
  42. #ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__
  43. ERROR:
  44. #endif
  45. __STDIO_STREAM_SET_ERROR(stream);
  46. __STDIO_STREAM_VALIDATE(stream);
  47. return EOF;
  48. }
  49. if (__STDIO_STREAM_IS_READING(stream)) {
  50. if (!__FEOF_UNLOCKED(stream)) {
  51. #ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__
  52. /* Need to seek to correct position if we have buffered
  53. * read data or ungots. If appending, we might as well
  54. * seek to the end.
  55. *
  56. * NOTE: If the OS does not handle append files correctly,
  57. * this is insufficient since we would need to seek to
  58. * the end even if not reading.*/
  59. if (((__STDIO_STREAM_BUFFER_RAVAIL(stream))
  60. || (stream->__modeflags & __FLAG_UNGOT))
  61. && fseek(stream, 0L,
  62. ((stream->__modeflags & __FLAG_APPEND)
  63. ? SEEK_END : SEEK_CUR))
  64. ) {
  65. /* fseek() only sets error indicator on read/write error. */
  66. goto ERROR;
  67. }
  68. #else
  69. /* C99 requires either at EOF or currently not reading. */
  70. __UNDEFINED_OR_NONPORTABLE;
  71. goto DO_EBADF;
  72. #endif
  73. }
  74. __STDIO_STREAM_CLEAR_READING_AND_UNGOTS(stream);
  75. __STDIO_STREAM_DISABLE_GETC(stream);
  76. /* Reaching EOF does not reset buffer pointers... */
  77. __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
  78. }
  79. __STDIO_STREAM_SET_WRITING(stream);
  80. if (__STDIO_STREAM_IS_NARROW_FBF(stream)) {
  81. __STDIO_STREAM_ENABLE_PUTC(stream);
  82. }
  83. __STDIO_STREAM_VALIDATE(stream);
  84. return 0;
  85. }