if f_in == f_out then don't close one of them
[rsync/rsync.git] / io.c
diff --git a/io.c b/io.c
index 52c4cb1..b48ae0f 100644 (file)
--- a/io.c
+++ b/io.c
@@ -45,8 +45,8 @@ static int buffer_f_in = -1;
 
 void setup_nonblocking(int f_in,int f_out)
 {
-  set_blocking(f_out,0);
-  buffer_f_in = f_in;
+       set_blocking(f_out,0);
+       buffer_f_in = f_in;
 }
 
 
@@ -61,39 +61,42 @@ static int read_buffer_size;
  * ssh will clag up. Uggh.  */
 static void read_check(int f)
 {
-  int n;
+       int n;
 
-  if (f == -1) return;
+       if (f == -1) return;
 
-  if (read_buffer_len == 0) {
-    read_buffer_p = read_buffer;
-  }
+       if (read_buffer_len == 0) {
+               read_buffer_p = read_buffer;
+       }
 
-  if ((n=num_waiting(f)) <= 0)
-    return;
+       if ((n=num_waiting(f)) <= 0)
+               return;
 
-  /* things could deteriorate if we read in really small chunks */
-  if (n < 10) n = 1024;
+       /* things could deteriorate if we read in really small chunks */
+       if (n < 10) n = 1024;
 
-  if (read_buffer_p != read_buffer) {
-    memmove(read_buffer,read_buffer_p,read_buffer_len);
-    read_buffer_p = read_buffer;
-  }
+       if (n > MAX_READ_BUFFER/4)
+               n = MAX_READ_BUFFER/4;
 
-  if (n > (read_buffer_size - read_buffer_len)) {
-    read_buffer_size += n;
-    if (!read_buffer)
-      read_buffer = (char *)malloc(read_buffer_size);
-    else
-      read_buffer = (char *)realloc(read_buffer,read_buffer_size);
-    if (!read_buffer) out_of_memory("read check");      
-    read_buffer_p = read_buffer;      
-  }
+       if (read_buffer_p != read_buffer) {
+               memmove(read_buffer,read_buffer_p,read_buffer_len);
+               read_buffer_p = read_buffer;
+       }
 
-  n = read(f,read_buffer+read_buffer_len,n);
-  if (n > 0) {
-    read_buffer_len += n;
-  }
+       if (n > (read_buffer_size - read_buffer_len)) {
+               read_buffer_size += n;
+               if (!read_buffer)
+                       read_buffer = (char *)malloc(read_buffer_size);
+               else
+                       read_buffer = (char *)realloc(read_buffer,read_buffer_size);
+               if (!read_buffer) out_of_memory("read check");      
+               read_buffer_p = read_buffer;      
+       }
+
+       n = read(f,read_buffer+read_buffer_len,n);
+       if (n > 0) {
+               read_buffer_len += n;
+       }
 }
 
 static time_t last_io;
@@ -301,7 +304,7 @@ int write_file(int f,char *buf,int len)
 }
 
 
-static int writefd(int fd,char *buf,int len)
+static int writefd_unbuffered(int fd,char *buf,int len)
 {
   int total = 0;
   fd_set w_fds, r_fds;
@@ -334,38 +337,40 @@ static int writefd(int fd,char *buf,int len)
 
 
     if (ret == -1) {
-      read_check(buffer_f_in);
-
-      fd_count = fd+1;
-      FD_ZERO(&w_fds);
-      FD_ZERO(&r_fds);
-      FD_SET(fd,&w_fds);
-      if (buffer_f_in != -1) {
-             FD_SET(buffer_f_in,&r_fds);
-             if (buffer_f_in > fd) 
-                     fd_count = buffer_f_in+1;
-      }
-
-      tv.tv_sec = BLOCKING_TIMEOUT;
-      tv.tv_usec = 0;
-      count = select(fd_count,buffer_f_in == -1? NULL: &r_fds,
-                    &w_fds,NULL,&tv);
-      if (count == -1 && errno != EINTR) {
-             if (verbose > 1) 
-                     rprintf(FERROR,"select error: %s\n", strerror(errno));
-             exit_cleanup(1);
-      }
-
-      if (count == 0) {
-             check_timeout();
-             continue;
-      }
+           if (read_buffer_len < MAX_READ_BUFFER)
+                   read_check(buffer_f_in);
+
+           fd_count = fd+1;
+           FD_ZERO(&w_fds);
+           FD_ZERO(&r_fds);
+           FD_SET(fd,&w_fds);
+           if (buffer_f_in != -1) {
+                   FD_SET(buffer_f_in,&r_fds);
+                   if (buffer_f_in > fd) 
+                           fd_count = buffer_f_in+1;
+           }
+
+           tv.tv_sec = BLOCKING_TIMEOUT;
+           tv.tv_usec = 0;
+           count = select(fd_count,buffer_f_in == -1? NULL: &r_fds,
+                          &w_fds,NULL,&tv);
+
+           if (count == -1 && errno != EINTR) {
+                   if (verbose > 1) 
+                           rprintf(FERROR,"select error: %s\n", strerror(errno));
+                   exit_cleanup(1);
+           }
+
+           if (count == 0) {
+                   check_timeout();
+                   continue;
+           }
       
-      if (FD_ISSET(fd, &w_fds)) {
-             got_select = 1;
-      }
+           if (FD_ISSET(fd, &w_fds)) {
+                   got_select = 1;
+           }
     } else {
-      total += ret;
+           total += ret;
     }
   }
 
@@ -375,6 +380,58 @@ static int writefd(int fd,char *buf,int len)
   return total;
 }
 
+static char *io_buffer;
+static int io_buffer_count;
+
+void io_start_buffering(int fd)
+{
+       io_buffer = (char *)malloc(IO_BUFFER_SIZE);
+       if (!io_buffer) out_of_memory("writefd");
+       io_buffer_count = 0;
+}
+
+void io_end_buffering(int fd)
+{
+       if (io_buffer_count) {
+               if (writefd_unbuffered(fd, io_buffer, 
+                                      io_buffer_count) != 
+                   io_buffer_count) {
+                       rprintf(FERROR,"write failed\n");
+                       exit_cleanup(1);
+               }
+               io_buffer_count = 0;
+       }
+       free(io_buffer);
+       io_buffer = NULL;
+}
+
+static int writefd(int fd,char *buf,int len1)
+{
+       int len = len1;
+
+       if (!io_buffer) return writefd_unbuffered(fd, buf, len);
+
+       while (len) {
+               int n = MIN(len, IO_BUFFER_SIZE-io_buffer_count);
+               if (n > 0) {
+                       memcpy(io_buffer+io_buffer_count, buf, n);
+                       buf += n;
+                       len -= n;
+                       io_buffer_count += n;
+               }
+               
+               if (io_buffer_count == IO_BUFFER_SIZE) {
+                       if (writefd_unbuffered(fd, io_buffer, 
+                                              io_buffer_count) != 
+                           io_buffer_count) {
+                               return -1;
+                       }
+                       io_buffer_count = 0;
+               }
+       }
+
+       return len1;
+}
 
 
 void write_int(int f,int32 x)
@@ -469,13 +526,7 @@ void io_printf(int fd, const char *format, ...)
        int len;
        
        va_start(ap, format);
-
-#if HAVE_VSNPRINTF
-       len = vsnprintf(buf, sizeof(buf)-1, format, ap);
-#else
-       vsprintf(buf, format, ap);
-       len = strlen(buf);
-#endif
+       len = vslprintf(buf, sizeof(buf)-1, format, ap);
        va_end(ap);
 
        if (len < 0) exit_cleanup(1);