_WRITE.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. libc_hidden_proto(write)
  9. /* Given a writing stream with no buffered output, write the
  10. * data in 'buf' (which may be the stream's bufstart) of size
  11. * 'bufsize' to the stream. If a write error occurs, set the
  12. * stream's error indicator and (if buffering) buffer as much
  13. * data as possible (FBF) or only up to '\n' (LBF) to implement
  14. * "as if fputc()" clause in the standard.
  15. *
  16. * Returns the number of bytes written and/or buffered.
  17. *
  18. * Notes:
  19. * Calling with bufsize == 0 is permitted, and buf is ignored in
  20. * that case.
  21. * We implement fflush() by setting bufpos to bufstart and passing
  22. * bufstart as the buf arg. If there is a write error, the
  23. * unwritten buffered data will simply be moved to the beginning
  24. * of the buffer. Since the data obviously fits in the buffer
  25. * and since there will be no '\n' chars in the buffer in the LBF
  26. * case, no data will be lost.
  27. * NOT THREADSAFE! Assumes stream already locked if necessary.
  28. */
  29. size_t attribute_hidden __stdio_WRITE(register FILE *stream,
  30. register const unsigned char *buf, size_t bufsize)
  31. {
  32. size_t todo;
  33. ssize_t rv, stodo;
  34. __STDIO_STREAM_VALIDATE(stream);
  35. assert(stream->__filedes >= -1);
  36. assert(__STDIO_STREAM_IS_WRITING(stream));
  37. assert(!__STDIO_STREAM_BUFFER_WUSED(stream)); /* Buffer must be empty. */
  38. todo = bufsize;
  39. do {
  40. if (todo == 0) { /* Done? */
  41. __STDIO_STREAM_VALIDATE(stream);
  42. return bufsize;
  43. }
  44. stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX;
  45. if ((rv = __WRITE(stream, buf, stodo)) >= 0) {
  46. #ifdef __UCLIBC_MJN3_ONLY__
  47. #warning TODO: Make custom stream write return check optional.
  48. #endif
  49. #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
  50. assert(rv <= stodo);
  51. if (rv > stodo) { /* Wrote more than stodo! */
  52. /* abort(); */
  53. }
  54. #endif
  55. todo -= rv;
  56. buf += rv;
  57. } else
  58. #ifdef __UCLIBC_MJN3_ONLY__
  59. #warning EINTR?
  60. #endif
  61. /* if (errno != EINTR) */
  62. {
  63. __STDIO_STREAM_SET_ERROR(stream);
  64. #ifdef __STDIO_BUFFERS
  65. if ((stodo = __STDIO_STREAM_BUFFER_SIZE(stream)) != 0) {
  66. unsigned char *s;
  67. if (stodo > todo) {
  68. stodo = todo;
  69. }
  70. s = stream->__bufstart;
  71. do {
  72. if (((*s = *buf) == '\n')
  73. && __STDIO_STREAM_IS_LBF(stream)
  74. ) {
  75. break;
  76. }
  77. ++s;
  78. ++buf;
  79. } while (--stodo);
  80. stream->__bufpos = s;
  81. todo -= (s - stream->__bufstart);
  82. }
  83. #endif /* __STDIO_BUFFERS */
  84. __STDIO_STREAM_VALIDATE(stream);
  85. return bufsize - todo;
  86. }
  87. } while (1);
  88. }