netinet/in.h: add IPPROTO_MH
[uclibc-ng.git] / libc / stdio / _WRITE.c
blobf95bd1ba90ddd4bdaf32717cb7862bfa706423c3
1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
3 * GNU Library General Public License (LGPL) version 2 or later.
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
6 */
8 #include "_stdio.h"
11 /* Given a writing stream with no buffered output, write the
12 * data in 'buf' (which may be the stream's bufstart) of size
13 * 'bufsize' to the stream. If a write error occurs, set the
14 * stream's error indicator and (if buffering) buffer as much
15 * data as possible (FBF) or only up to '\n' (LBF) to implement
16 * "as if fputc()" clause in the standard.
18 * Returns the number of bytes written and/or buffered.
20 * Notes:
21 * Calling with bufsize == 0 is permitted, and buf is ignored in
22 * that case.
23 * We implement fflush() by setting bufpos to bufstart and passing
24 * bufstart as the buf arg. If there is a write error, the
25 * unwritten buffered data will simply be moved to the beginning
26 * of the buffer. Since the data obviously fits in the buffer
27 * and since there will be no '\n' chars in the buffer in the LBF
28 * case, no data will be lost.
29 * NOT THREADSAFE! Assumes stream already locked if necessary.
32 size_t attribute_hidden __stdio_WRITE(register FILE *stream,
33 register const unsigned char *buf, size_t bufsize)
35 size_t todo;
36 ssize_t rv, stodo;
38 __STDIO_STREAM_VALIDATE(stream);
39 assert(stream->__filedes >= -2);
40 assert(__STDIO_STREAM_IS_WRITING(stream));
41 assert(!__STDIO_STREAM_BUFFER_WUSED(stream)); /* Buffer must be empty. */
43 todo = bufsize;
45 while (todo != 0) {
46 stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX;
47 rv = __WRITE(stream, (char *) buf, stodo);
48 if (rv >= 0) {
49 #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
50 assert(rv <= stodo);
51 if (rv > stodo) { /* Wrote more than stodo! */
52 /* abort(); */
54 #endif
55 todo -= rv;
56 buf += rv;
57 } else {
59 __STDIO_STREAM_SET_ERROR(stream);
61 /* We buffer data on "transient" errors, but discard it
62 * on "hard" ones. Example of a hard error:
64 * close(fileno(stdout));
65 * printf("Hi there 1\n"); // EBADF
66 * dup2(good_fd, fileno(stdout));
67 * printf("Hi there 2\n"); // buffers new data
69 * This program should not print "Hi there 1" to good_fd.
70 * The rationale is that the caller of writing operation
71 * should check for error and act on it.
72 * If he didn't, then future users of the stream
73 * have no idea what to do.
74 * It's least confusing to at least not burden them with
75 * some hidden buffered crap in the buffer.
77 if (errno != EINTR && errno != EAGAIN) {
78 /* do we have other "soft" errors? */
79 bufsize -= todo;
80 break;
82 #ifdef __STDIO_BUFFERS
83 stodo = __STDIO_STREAM_BUFFER_SIZE(stream);
84 if (stodo != 0) {
85 unsigned char *s;
87 if (stodo > todo) {
88 stodo = todo;
91 s = stream->__bufstart;
93 do {
94 *s = *buf;
95 if ((*s == '\n')
96 && __STDIO_STREAM_IS_LBF(stream)
97 ) {
98 break;
100 ++s;
101 ++buf;
102 } while (--stodo);
104 stream->__bufpos = s;
106 todo -= (s - stream->__bufstart);
108 #endif /* __STDIO_BUFFERS */
110 bufsize -= todo;
111 break;
115 __STDIO_STREAM_VALIDATE(stream);
116 return bufsize;