/* -*- c-file-style: "linux" -*-
- *
- * Copyright (C) 1996-2001 by Andrew Tridgell
+ *
+ * Copyright (C) 1996-2001 by Andrew Tridgell
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
/**
* @file io.c
*
- * Socket and pipe IO utilities used in rsync.
+ * Socket and pipe I/O utilities used in rsync.
*
* rsync provides its own multiplexing system, which is used to send
* stderr and stdout over a single socket. We need this because
* not very helpful. So instead we try to make io_phase_name point to
* something useful.
*
- * For buffered/multiplexed IO these names will be somewhat
+ * For buffered/multiplexed I/O these names will be somewhat
* approximate; perhaps for ease of support we would rather make the
- * buffer always flush when a single application-level IO finishes.
+ * buffer always flush when a single application-level I/O finishes.
*
* @todo Perhaps we want some simple stack functionality, but there's
* no need to overdo it.
if (last_io && io_timeout && (t-last_io) >= io_timeout) {
if (!am_server && !am_daemon) {
- rprintf(FERROR,"io timeout after %d seconds - exiting\n",
+ rprintf(FERROR, "io timeout after %d seconds - exiting\n",
(int)(t-last_io));
}
exit_cleanup(RERR_TIMEOUT);
/** Setup the fd used to receive MSG_* messages. Only needed when
* we're the generator because the sender and receiver both use the
- * multiplexed IO setup. */
+ * multiplexed I/O setup. */
void set_msg_fd_in(int fd)
{
msg_fd_in = fd;
/** Setup the fd used to send our MSG_* messages. Only needed when
* we're the receiver because the generator and the sender both use
- * the multiplexed IO setup. */
+ * the multiplexed I/O setup. */
void set_msg_fd_out(int fd)
{
msg_fd_out = fd;
switch (tag) {
case MSG_DONE:
- if (len != 0)
+ if (len != 0) {
+ rprintf(FERROR, "invalid message %d:%d\n", tag, len);
exit_cleanup(RERR_STREAMIO);
+ }
redo_list_add(-1);
break;
case MSG_REDO:
- if (len != 4)
+ if (len != 4) {
+ rprintf(FERROR, "invalid message %d:%d\n", tag, len);
exit_cleanup(RERR_STREAMIO);
+ }
read_loop(fd, buf, 4);
redo_list_add(IVAL(buf,0));
break;
}
break;
default:
+ rprintf(FERROR, "unknown message %d:%d\n", tag, len);
exit_cleanup(RERR_STREAMIO);
}
if (kludge_around_eof)
exit_cleanup(0);
else {
- rprintf(FERROR,
- "%s: connection unexpectedly closed "
+ rprintf(FERROR, RSYNC_NAME ": connection unexpectedly closed "
"(%.0f bytes read so far)\n",
- RSYNC_NAME, (double)stats.total_read);
+ (double)stats.total_read);
exit_cleanup(RERR_STREAMIO);
}
/* this prevents us trying to write errors on a dead socket */
io_multiplexing_close();
- rprintf(FERROR, "%s: read error: %s\n",
- RSYNC_NAME, strerror(err));
+ rsyserr(FERROR, err, "read error");
exit_cleanup(RERR_STREAMIO);
}
/**
- * Read from a socket with IO timeout. return the number of bytes
+ * Read from a socket with I/O timeout. return the number of bytes
* read. If no bytes can be read then exit, never return a number <= 0.
*
* TODO: If the remote shell connection fails, then current versions
*/
static int read_timeout(int fd, char *buf, size_t len)
{
- int n, ret=0;
+ int n, ret = 0;
io_flush(NORMAL_FLUSH);
whine_about_eof();
return -1; /* doesn't return */
} else if (n < 0) {
- if (errno == EINTR || errno == EWOULDBLOCK ||
- errno == EAGAIN)
+ if (errno == EINTR || errno == EWOULDBLOCK
+ || errno == EAGAIN)
continue;
die_from_readerr(errno);
}
/**
* Read from the file descriptor handling multiplexing - return number
* of bytes read.
- *
- * Never returns <= 0.
+ *
+ * Never returns <= 0.
*/
static int read_unbuffered(int fd, char *buf, size_t len)
{
static void readfd(int fd, char *buffer, size_t N)
{
int ret;
- size_t total=0;
+ size_t total = 0;
while (total < N) {
ret = read_unbuffered(fd, buffer + total, N-total);
if (msg_fd_in >= 0) {
FD_ZERO(&r_fds);
FD_SET(msg_fd_in,&r_fds);
- if (msg_fd_in > fd_count)
+ if (msg_fd_in > fd_count)
fd_count = msg_fd_in;
}
/* Don't try to write errors back
* across the stream */
io_multiplexing_close();
- rprintf(FERROR, RSYNC_NAME
- ": writefd_unbuffered failed to write %ld bytes: phase \"%s\": %s\n",
- (long) len, io_write_phase,
- strerror(errno));
+ rsyserr(FERROR, errno,
+ "writefd_unbuffered failed to write %ld bytes: phase \"%s\"",
+ (long) len, io_write_phase);
exit_cleanup(RERR_STREAMIO);
}
sleep_for_bwlimit(ret);
-
+
total += ret;
if (io_timeout)
void io_flush(int flush_it_all)
{
int fd = multiplex_out_fd;
-
+
msg_list_push(flush_it_all);
if (!io_buffer_count || no_flush)
/**
- * Read a line of up to @p maxlen characters into @p buf. Does not
- * contain a trailing newline or carriage return.
+ * Read a line of up to @p maxlen characters into @p buf (not counting
+ * the trailing null). Strips the (required) trailing newline and all
+ * carriage returns.
*
- * @return 1 for success; 0 for io error or truncation.
+ * @return 1 for success; 0 for I/O error or truncation.
**/
int read_line(int f, char *buf, size_t maxlen)
{
read_buf(f, buf, 1);
if (buf[0] == 0)
return 0;
- if (buf[0] == '\n') {
- buf[0] = 0;
+ if (buf[0] == '\n')
break;
- }
if (buf[0] != '\r') {
buf++;
maxlen--;
}
}
- if (maxlen == 0) {
- *buf = 0;
- return 0;
- }
-
- return 1;
+ *buf = '\0';
+ return maxlen > 0;
}
void io_printf(int fd, const char *format, ...)
{
- va_list ap;
+ va_list ap;
char buf[1024];
int len;