OK, we can now get phase messages if we fail in send_file_entry
[rsync/rsync.git] / io.c
CommitLineData
7a24c346 1/* -*- c-file-style: "linux" -*-
880da007
MP
2 *
3 * Copyright (C) 1996-2001 by Andrew Tridgell
4 * Copyright (C) Paul Mackerras 1996
5 * Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
720b47f2 21
87ee2481 22/**
87ee2481
MP
23 * @file io.c
24 *
25 * Socket and pipe IO utilities used in rsync.
26 *
27 * rsync provides its own multiplexing system, which is used to send
28 * stderr and stdout over a single socket. We need this because
29 * stdout normally carries the binary data stream, and stderr all our
30 * error messages.
31 *
32 * For historical reasons this is off during the start of the
33 * connection, but it's switched on quite early using
34 * io_start_multiplex_out() and io_start_multiplex_in().
35 **/
720b47f2 36
720b47f2
AT
37#include "rsync.h"
38
880da007 39/** If no timeout is specified then use a 60 second select timeout */
8cd9fd4e
AT
40#define SELECT_TIMEOUT 60
41
8d9dc9f9
AT
42static int io_multiplexing_out;
43static int io_multiplexing_in;
679e7657
AT
44static int multiplex_in_fd;
45static int multiplex_out_fd;
8d9dc9f9 46static time_t last_io;
7a55d06e
MP
47static int no_flush;
48
49extern int bwlimit;
720b47f2 50extern int verbose;
6ba9279f 51extern int io_timeout;
a800434a 52extern struct stats stats;
720b47f2 53
7a55d06e 54
98b332ed
MP
55/**
56 * The connection might be dropped at some point; perhaps because the
57 * remote instance crashed. Just giving the offset on the stream is
58 * not very helpful. So instead we try to make io_phase_name point to
59 * something useful.
eca2adb4
MP
60 *
61 * @todo Perhaps we want some simple stack functionality, but there's
62 * no need to overdo it.
98b332ed 63 **/
eca2adb4
MP
64const char *io_write_phase = "unknown";
65const char *io_read_phase = "unknown";
98b332ed
MP
66
67
7a55d06e
MP
68/** Ignore EOF errors while reading a module listing if the remote
69 version is 24 or less. */
70int kludge_around_eof = False;
71
72
554e0a8d 73static int io_error_fd = -1;
720b47f2 74
9dd891bb 75static void read_loop(int fd, char *buf, size_t len);
ff41a59f 76
8d9dc9f9
AT
77static void check_timeout(void)
78{
0adb99b9 79 extern int am_server, am_daemon;
8d9dc9f9 80 time_t t;
90ba34e2
AT
81
82 err_list_push();
8d9dc9f9
AT
83
84 if (!io_timeout) return;
85
86 if (!last_io) {
87 last_io = time(NULL);
88 return;
89 }
90
91 t = time(NULL);
92
86ffe37f 93 if (last_io && io_timeout && (t-last_io) >= io_timeout) {
0adb99b9 94 if (!am_server && !am_daemon) {
ce6c7c63 95 rprintf(FERROR,"io timeout after %d seconds - exiting\n",
0adb99b9
AT
96 (int)(t-last_io));
97 }
65417579 98 exit_cleanup(RERR_TIMEOUT);
8d9dc9f9
AT
99 }
100}
101
880da007 102/** Setup the fd used to propogate errors */
554e0a8d
AT
103void io_set_error_fd(int fd)
104{
105 io_error_fd = fd;
106}
107
880da007 108/** Read some data from the error fd and write it to the write log code */
554e0a8d
AT
109static void read_error_fd(void)
110{
111 char buf[200];
06ce139f 112 size_t n;
554e0a8d 113 int fd = io_error_fd;
ff41a59f
AT
114 int tag, len;
115
8886f8d0
MP
116 /* io_error_fd is temporarily disabled -- is this meant to
117 * prevent indefinite recursion? */
554e0a8d
AT
118 io_error_fd = -1;
119
ff41a59f
AT
120 read_loop(fd, buf, 4);
121 tag = IVAL(buf, 0);
122
123 len = tag & 0xFFFFFF;
124 tag = tag >> 24;
125 tag -= MPLEX_BASE;
126
127 while (len) {
128 n = len;
06ce139f
MP
129 if (n > (sizeof(buf)-1))
130 n = sizeof(buf)-1;
ff41a59f
AT
131 read_loop(fd, buf, n);
132 rwrite((enum logcode)tag, buf, n);
133 len -= n;
554e0a8d
AT
134 }
135
136 io_error_fd = fd;
137}
138
720b47f2 139
880da007
MP
140/**
141 * It's almost always an error to get an EOF when we're trying to read
142 * from the network, because the protocol is self-terminating.
143 *
144 * However, there is one unfortunate cases where it is not, which is
145 * rsync <2.4.6 sending a list of modules on a server, since the list
146 * is terminated by closing the socket. So, for the section of the
147 * program where that is a problem (start_socket_client),
148 * kludge_around_eof is True and we just exit.
149 */
7a55d06e
MP
150static void whine_about_eof (void)
151{
7a55d06e
MP
152 if (kludge_around_eof)
153 exit_cleanup (0);
154 else {
155 rprintf (FERROR,
156 "%s: connection unexpectedly closed "
157 "(%.0f bytes read so far)\n",
158 RSYNC_NAME, (double)stats.total_read);
159
160 exit_cleanup (RERR_STREAMIO);
161 }
162}
720b47f2 163
7a55d06e
MP
164
165static void die_from_readerr (int err)
166{
167 /* this prevents us trying to write errors on a dead socket */
168 io_multiplexing_close();
169
170 rprintf(FERROR, "%s: read error: %s\n",
171 RSYNC_NAME, strerror (err));
172 exit_cleanup(RERR_STREAMIO);
173}
174
175
880da007 176/**
c3563c46
MP
177 * Read from a socket with IO timeout. return the number of bytes
178 * read. If no bytes can be read then exit, never return a number <= 0.
179 *
8886f8d0
MP
180 * TODO: If the remote shell connection fails, then current versions
181 * actually report an "unexpected EOF" error here. Since it's a
182 * fairly common mistake to try to use rsh when ssh is required, we
183 * should trap that: if we fail to read any data at all, we should
184 * give a better explanation. We can tell whether the connection has
185 * started by looking e.g. at whether the remote version is known yet.
c3563c46 186 */
9dd891bb 187static int read_timeout (int fd, char *buf, size_t len)
8d9dc9f9 188{
4c36ddbe
AT
189 int n, ret=0;
190
ea2111d1
AT
191 io_flush();
192
4c36ddbe 193 while (ret == 0) {
7a55d06e 194 /* until we manage to read *something* */
4c36ddbe
AT
195 fd_set fds;
196 struct timeval tv;
554e0a8d 197 int fd_count = fd+1;
a57873b7 198 int count;
4c36ddbe
AT
199
200 FD_ZERO(&fds);
201 FD_SET(fd, &fds);
554e0a8d
AT
202 if (io_error_fd != -1) {
203 FD_SET(io_error_fd, &fds);
204 if (io_error_fd > fd) fd_count = io_error_fd+1;
205 }
206
8cd9fd4e 207 tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
4c36ddbe
AT
208 tv.tv_usec = 0;
209
554e0a8d
AT
210 errno = 0;
211
a57873b7
AT
212 count = select(fd_count, &fds, NULL, NULL, &tv);
213
214 if (count == 0) {
215 check_timeout();
216 }
217
218 if (count <= 0) {
554e0a8d
AT
219 if (errno == EBADF) {
220 exit_cleanup(RERR_SOCKETIO);
221 }
4c36ddbe
AT
222 continue;
223 }
224
554e0a8d
AT
225 if (io_error_fd != -1 && FD_ISSET(io_error_fd, &fds)) {
226 read_error_fd();
227 }
228
229 if (!FD_ISSET(fd, &fds)) continue;
230
4c36ddbe
AT
231 n = read(fd, buf, len);
232
8d9dc9f9
AT
233 if (n > 0) {
234 buf += n;
235 len -= n;
4c36ddbe
AT
236 ret += n;
237 if (io_timeout)
238 last_io = time(NULL);
239 continue;
7a55d06e
MP
240 } else if (n == 0) {
241 whine_about_eof ();
242 return -1; /* doesn't return */
243 } else if (n == -1) {
244 if (errno == EINTR || errno == EWOULDBLOCK ||
245 errno == EAGAIN)
246 continue;
247 else
248 die_from_readerr (errno);
8d9dc9f9 249 }
4c36ddbe 250 }
8d9dc9f9 251
4c36ddbe
AT
252 return ret;
253}
8d9dc9f9 254
7a55d06e
MP
255
256
257
880da007
MP
258/**
259 * Continue trying to read len bytes - don't return until len has been
260 * read.
261 **/
9dd891bb 262static void read_loop (int fd, char *buf, size_t len)
4c36ddbe
AT
263{
264 while (len) {
265 int n = read_timeout(fd, buf, len);
266
267 buf += n;
268 len -= n;
8d9dc9f9
AT
269 }
270}
271
7a55d06e
MP
272
273/**
274 * Read from the file descriptor handling multiplexing - return number
275 * of bytes read.
276 *
277 * Never returns <= 0.
278 */
9dd891bb 279static int read_unbuffered(int fd, char *buf, size_t len)
8d9dc9f9 280{
6fe25398 281 static size_t remaining;
909ce14f 282 int tag, ret = 0;
8d9dc9f9
AT
283 char line[1024];
284
7a55d06e 285 if (!io_multiplexing_in || fd != multiplex_in_fd)
4c36ddbe 286 return read_timeout(fd, buf, len);
8d9dc9f9
AT
287
288 while (ret == 0) {
289 if (remaining) {
290 len = MIN(len, remaining);
291 read_loop(fd, buf, len);
292 remaining -= len;
293 ret = len;
294 continue;
295 }
296
909ce14f 297 read_loop(fd, line, 4);
ff41a59f 298 tag = IVAL(line, 0);
679e7657 299
8d9dc9f9
AT
300 remaining = tag & 0xFFFFFF;
301 tag = tag >> 24;
302
909ce14f
MP
303 if (tag == MPLEX_BASE)
304 continue;
8d9dc9f9
AT
305
306 tag -= MPLEX_BASE;
307
308 if (tag != FERROR && tag != FINFO) {
909ce14f 309 rprintf(FERROR, "unexpected tag %d\n", tag);
65417579 310 exit_cleanup(RERR_STREAMIO);
8d9dc9f9
AT
311 }
312
909ce14f
MP
313 if (remaining > sizeof(line) - 1) {
314 rprintf(FERROR, "multiplexing overflow %d\n\n",
8d9dc9f9 315 remaining);
65417579 316 exit_cleanup(RERR_STREAMIO);
8d9dc9f9
AT
317 }
318
319 read_loop(fd, line, remaining);
320 line[remaining] = 0;
321
909ce14f 322 rprintf((enum logcode) tag, "%s", line);
8d9dc9f9
AT
323 remaining = 0;
324 }
325
326 return ret;
327}
328
329
909ce14f 330
880da007
MP
331/**
332 * Do a buffered read from @p fd. Don't return until all @p n bytes
333 * have been read. If all @p n can't be read then exit with an
334 * error.
335 **/
9dd891bb 336static void readfd (int fd, char *buffer, size_t N)
720b47f2 337{
6ba9279f 338 int ret;
06ce139f 339 size_t total=0;
6ba9279f 340
6ba9279f 341 while (total < N) {
8d9dc9f9
AT
342 io_flush();
343
7a55d06e 344 ret = read_unbuffered (fd, buffer + total, N-total);
6ba9279f 345 total += ret;
7f28dbee 346 }
1b7c47cb
AT
347
348 stats.total_read += total;
720b47f2
AT
349}
350
351
b7922338 352int32 read_int(int f)
720b47f2 353{
4c36ddbe 354 char b[4];
d730b113
AT
355 int32 ret;
356
4c36ddbe 357 readfd(f,b,4);
d730b113
AT
358 ret = IVAL(b,0);
359 if (ret == (int32)0xffffffff) return -1;
360 return ret;
720b47f2
AT
361}
362
71c46176 363int64 read_longint(int f)
3a6a366f
AT
364{
365 extern int remote_version;
71c46176 366 int64 ret;
3a6a366f
AT
367 char b[8];
368 ret = read_int(f);
71c46176 369
8de330a3
AT
370 if ((int32)ret != (int32)0xffffffff) {
371 return ret;
372 }
71c46176 373
3bee6733 374#ifdef NO_INT64
9486289c 375 rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
65417579 376 exit_cleanup(RERR_UNSUPPORTED);
71c46176
AT
377#else
378 if (remote_version >= 16) {
4c36ddbe 379 readfd(f,b,8);
71c46176 380 ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
3a6a366f 381 }
71c46176
AT
382#endif
383
3a6a366f
AT
384 return ret;
385}
386
9dd891bb 387void read_buf(int f,char *buf,size_t len)
720b47f2 388{
4c36ddbe 389 readfd(f,buf,len);
720b47f2
AT
390}
391
9dd891bb 392void read_sbuf(int f,char *buf,size_t len)
575f2fca 393{
7a55d06e 394 read_buf (f,buf,len);
575f2fca
AT
395 buf[len] = 0;
396}
397
182dca5c
AT
398unsigned char read_byte(int f)
399{
4c36ddbe 400 unsigned char c;
7a55d06e 401 read_buf (f, (char *)&c, 1);
4c36ddbe 402 return c;
182dca5c 403}
720b47f2 404
880da007 405
08571358
MP
406/**
407 * Sleep after writing to limit I/O bandwidth usage.
408 *
409 * @todo Rather than sleeping after each write, it might be better to
410 * use some kind of averaging. The current algorithm seems to always
411 * use a bit less bandwidth than specified, because it doesn't make up
412 * for slow periods. But arguably this is a feature. In addition, we
413 * ought to take the time used to write the data into account.
414 **/
415static void sleep_for_bwlimit(int bytes_written)
416{
417 struct timeval tv;
418
419 if (!bwlimit)
420 return;
e681e820
MP
421
422 assert(bytes_written > 0);
423 assert(bwlimit > 0);
08571358 424
08571358 425 tv.tv_usec = bytes_written * 1000 / bwlimit;
e681e820
MP
426 tv.tv_sec = tv.tv_usec / 1000000;
427 tv.tv_usec = tv.tv_usec % 1000000;
08571358 428
98b332ed 429 select(0, NULL, NULL, NULL, &tv);
08571358
MP
430}
431
432
880da007
MP
433/**
434 * Write len bytes to the file descriptor @p fd.
435 *
436 * This function underlies the multiplexing system. The body of the
437 * application never calls this function directly.
438 **/
9dd891bb 439static void writefd_unbuffered(int fd,char *buf,size_t len)
720b47f2 440{
06ce139f 441 size_t total = 0;
8d9dc9f9 442 fd_set w_fds, r_fds;
4c36ddbe 443 int fd_count, count;
8d9dc9f9 444 struct timeval tv;
720b47f2 445
90ba34e2
AT
446 err_list_push();
447
e44f9a12
AT
448 no_flush++;
449
4c36ddbe 450 while (total < len) {
8d9dc9f9
AT
451 FD_ZERO(&w_fds);
452 FD_ZERO(&r_fds);
453 FD_SET(fd,&w_fds);
554e0a8d 454 fd_count = fd;
4c36ddbe 455
554e0a8d
AT
456 if (io_error_fd != -1) {
457 FD_SET(io_error_fd,&r_fds);
458 if (io_error_fd > fd_count)
459 fd_count = io_error_fd;
8d9dc9f9
AT
460 }
461
8cd9fd4e 462 tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
8d9dc9f9 463 tv.tv_usec = 0;
4c36ddbe 464
554e0a8d
AT
465 errno = 0;
466
467 count = select(fd_count+1,
08f15335 468 io_error_fd != -1?&r_fds:NULL,
4c36ddbe 469 &w_fds,NULL,
8cd9fd4e 470 &tv);
4c36ddbe 471
a57873b7
AT
472 if (count == 0) {
473 check_timeout();
474 }
475
4c36ddbe 476 if (count <= 0) {
554e0a8d
AT
477 if (errno == EBADF) {
478 exit_cleanup(RERR_SOCKETIO);
479 }
8d9dc9f9
AT
480 continue;
481 }
4c36ddbe 482
554e0a8d
AT
483 if (io_error_fd != -1 && FD_ISSET(io_error_fd, &r_fds)) {
484 read_error_fd();
485 }
486
8d9dc9f9 487 if (FD_ISSET(fd, &w_fds)) {
06ce139f
MP
488 int ret;
489 size_t n = len-total;
f0359dd0 490 ret = write(fd,buf+total,n);
4c36ddbe
AT
491
492 if (ret == -1 && errno == EINTR) {
493 continue;
494 }
495
f0359dd0
AT
496 if (ret == -1 &&
497 (errno == EWOULDBLOCK || errno == EAGAIN)) {
e92ee128 498 msleep(1);
f0359dd0
AT
499 continue;
500 }
501
4c36ddbe 502 if (ret <= 0) {
befbfe61
MP
503 /* Don't try to write errors back
504 * across the stream */
505 io_multiplexing_close();
3ce0f9a6 506 rprintf(FERROR, RSYNC_NAME
98b332ed 507 ": writefd_unbuffered failed to write %ld bytes: phase \"%s\": %s\n",
eca2adb4 508 (long) len, io_write_phase,
ce6c7c63 509 strerror(errno));
65417579 510 exit_cleanup(RERR_STREAMIO);
4c36ddbe
AT
511 }
512
08571358 513 sleep_for_bwlimit(ret);
ef5d23eb 514
4c36ddbe 515 total += ret;
a800434a 516
4c36ddbe
AT
517 if (io_timeout)
518 last_io = time(NULL);
8d9dc9f9 519 }
4c36ddbe 520 }
e44f9a12
AT
521
522 no_flush--;
720b47f2
AT
523}
524
8d9dc9f9 525
d6dead6b
AT
526static char *io_buffer;
527static int io_buffer_count;
528
529void io_start_buffering(int fd)
530{
8d9dc9f9 531 if (io_buffer) return;
679e7657 532 multiplex_out_fd = fd;
ff41a59f 533 io_buffer = (char *)malloc(IO_BUFFER_SIZE);
d6dead6b
AT
534 if (!io_buffer) out_of_memory("writefd");
535 io_buffer_count = 0;
ff41a59f
AT
536}
537
880da007
MP
538/**
539 * Write an message to a multiplexed stream. If this fails then rsync
540 * exits.
541 **/
9dd891bb 542static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
ff41a59f
AT
543{
544 char buffer[4096];
06ce139f 545 size_t n = len;
8d9dc9f9 546
ff41a59f
AT
547 SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
548
6d7b6081
AT
549 if (n > (sizeof(buffer)-4)) {
550 n = sizeof(buffer)-4;
ff41a59f
AT
551 }
552
553 memcpy(&buffer[4], buf, n);
554 writefd_unbuffered(fd, buffer, n+4);
555
556 len -= n;
557 buf += n;
558
6d7b6081
AT
559 if (len) {
560 writefd_unbuffered(fd, buf, len);
561 }
d6dead6b
AT
562}
563
ff41a59f 564
8d9dc9f9 565void io_flush(void)
d6dead6b 566{
679e7657 567 int fd = multiplex_out_fd;
90ba34e2
AT
568
569 err_list_push();
570
e44f9a12 571 if (!io_buffer_count || no_flush) return;
8d9dc9f9
AT
572
573 if (io_multiplexing_out) {
0f3203c3 574 mplex_write(fd, FNONE, io_buffer, io_buffer_count);
8d9dc9f9 575 } else {
4c36ddbe 576 writefd_unbuffered(fd, io_buffer, io_buffer_count);
d6dead6b 577 }
8d9dc9f9
AT
578 io_buffer_count = 0;
579}
580
0ba48136 581
7b5c3eb0 582void io_end_buffering(void)
8d9dc9f9
AT
583{
584 io_flush();
585 if (!io_multiplexing_out) {
ff41a59f 586 free(io_buffer);
8d9dc9f9
AT
587 io_buffer = NULL;
588 }
d6dead6b
AT
589}
590
9dd891bb 591static void writefd(int fd,char *buf,size_t len)
d6dead6b 592{
1b7c47cb
AT
593 stats.total_written += len;
594
90ba34e2
AT
595 err_list_push();
596
554e0a8d 597 if (!io_buffer || fd != multiplex_out_fd) {
4c36ddbe
AT
598 writefd_unbuffered(fd, buf, len);
599 return;
600 }
d6dead6b
AT
601
602 while (len) {
7b5c3eb0 603 int n = MIN((int) len, IO_BUFFER_SIZE-io_buffer_count);
d6dead6b
AT
604 if (n > 0) {
605 memcpy(io_buffer+io_buffer_count, buf, n);
606 buf += n;
607 len -= n;
608 io_buffer_count += n;
609 }
610
8d9dc9f9 611 if (io_buffer_count == IO_BUFFER_SIZE) io_flush();
d6dead6b 612 }
d6dead6b 613}
720b47f2
AT
614
615
b7922338 616void write_int(int f,int32 x)
720b47f2 617{
8d9dc9f9
AT
618 char b[4];
619 SIVAL(b,0,x);
4c36ddbe 620 writefd(f,b,4);
720b47f2
AT
621}
622
7a24c346
MP
623
624/*
625 * Note: int64 may actually be a 32-bit type if ./configure couldn't find any
626 * 64-bit types on this platform.
627 */
71c46176 628void write_longint(int f, int64 x)
3a6a366f
AT
629{
630 extern int remote_version;
631 char b[8];
3a6a366f
AT
632
633 if (remote_version < 16 || x <= 0x7FFFFFFF) {
634 write_int(f, (int)x);
635 return;
636 }
637
8de330a3 638 write_int(f, (int32)0xFFFFFFFF);
3a6a366f
AT
639 SIVAL(b,0,(x&0xFFFFFFFF));
640 SIVAL(b,4,((x>>32)&0xFFFFFFFF));
641
4c36ddbe 642 writefd(f,b,8);
3a6a366f
AT
643}
644
9dd891bb 645void write_buf(int f,char *buf,size_t len)
720b47f2 646{
4c36ddbe 647 writefd(f,buf,len);
720b47f2
AT
648}
649
880da007 650/** Write a string to the connection */
6e4fb64e 651static void write_sbuf(int f,char *buf)
f0fca04e
AT
652{
653 write_buf(f, buf, strlen(buf));
654}
655
720b47f2 656
182dca5c
AT
657void write_byte(int f,unsigned char c)
658{
f0fca04e 659 write_buf(f,(char *)&c,1);
182dca5c
AT
660}
661
7a55d06e
MP
662
663
914cc65c
MP
664/**
665 * Read a line of up to @p maxlen characters into @p buf. Does not
666 * contain a trailing newline or carriage return.
667 *
668 * @return 1 for success; 0 for io error or truncation.
669 **/
9dd891bb 670int read_line(int f, char *buf, size_t maxlen)
f0fca04e
AT
671{
672 while (maxlen) {
528bfcd7 673 buf[0] = 0;
f0fca04e 674 read_buf(f, buf, 1);
914cc65c
MP
675 if (buf[0] == 0)
676 return 0;
f0fca04e
AT
677 if (buf[0] == '\n') {
678 buf[0] = 0;
679 break;
680 }
681 if (buf[0] != '\r') {
682 buf++;
683 maxlen--;
684 }
685 }
686 if (maxlen == 0) {
687 *buf = 0;
688 return 0;
689 }
528bfcd7 690
f0fca04e
AT
691 return 1;
692}
693
694
695void io_printf(int fd, const char *format, ...)
696{
697 va_list ap;
698 char buf[1024];
699 int len;
700
701 va_start(ap, format);
8950ac03 702 len = vsnprintf(buf, sizeof(buf), format, ap);
f0fca04e
AT
703 va_end(ap);
704
65417579 705 if (len < 0) exit_cleanup(RERR_STREAMIO);
f0fca04e
AT
706
707 write_sbuf(fd, buf);
708}
8d9dc9f9
AT
709
710
880da007 711/** Setup for multiplexing an error stream with the data stream */
8d9dc9f9
AT
712void io_start_multiplex_out(int fd)
713{
679e7657
AT
714 multiplex_out_fd = fd;
715 io_flush();
8d9dc9f9
AT
716 io_start_buffering(fd);
717 io_multiplexing_out = 1;
718}
719
880da007 720/** Setup for multiplexing an error stream with the data stream */
8d9dc9f9
AT
721void io_start_multiplex_in(int fd)
722{
679e7657
AT
723 multiplex_in_fd = fd;
724 io_flush();
8d9dc9f9
AT
725 io_multiplexing_in = 1;
726}
727
880da007 728/** Write an message to the multiplexed error stream */
9dd891bb 729int io_multiplex_write(enum logcode code, char *buf, size_t len)
8d9dc9f9
AT
730{
731 if (!io_multiplexing_out) return 0;
732
733 io_flush();
1b7c47cb 734 stats.total_written += (len+4);
ff41a59f 735 mplex_write(multiplex_out_fd, code, buf, len);
8d9dc9f9
AT
736 return 1;
737}
738
880da007 739/** Stop output multiplexing */
554e0a8d
AT
740void io_multiplexing_close(void)
741{
742 io_multiplexing_out = 0;
743}
744