home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / OPENSTEP / UNIX / Utilities / rsync-1.6.3-MIH / src / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-11  |  5.7 KB  |  298 lines

  1. /* 
  2.    Copyright (C) Andrew Tridgell 1996
  3.    Copyright (C) Paul Mackerras 1996
  4.    
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2 of the License, or
  8.    (at your option) any later version.
  9.    
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.    
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. /*
  21.   Utilities used in rsync 
  22.  
  23.   tridge, June 1996
  24.   */
  25. #include "rsync.h"
  26.  
  27. static int total_written = 0;
  28. static int total_read = 0;
  29.  
  30. extern int verbose;
  31. extern int sparse_files;
  32.  
  33. int write_total(void)
  34. {
  35.   return total_written;
  36. }
  37.  
  38. int read_total(void)
  39. {
  40.   return total_read;
  41. }
  42.  
  43. static int buffer_f_in = -1;
  44.  
  45. void setup_nonblocking(int f_in,int f_out)
  46. {
  47.   set_blocking(f_out,0);
  48.   buffer_f_in = f_in;
  49. }
  50.  
  51.  
  52. static char *read_buffer = NULL;
  53. static char *read_buffer_p = NULL;
  54. static int read_buffer_len = 0;
  55. static int read_buffer_size = 0;
  56.  
  57.  
  58. /* This function was added to overcome a deadlock problem when using
  59.  * ssh.  It looks like we can't allow our receive queue to get full or
  60.  * ssh will clag up. Uggh.  */
  61. static void read_check(int f)
  62. {
  63.   int n;
  64.  
  65.   if (read_buffer_len == 0) {
  66.     read_buffer_p = read_buffer;
  67.   }
  68.  
  69.   if ((n=num_waiting(f)) <= 0)
  70.     return;
  71.  
  72.   if (read_buffer_p != read_buffer) {
  73.     memmove(read_buffer,read_buffer_p,read_buffer_len);
  74.     read_buffer_p = read_buffer;
  75.   }
  76.  
  77.   if (n > (read_buffer_size - read_buffer_len)) {
  78.     read_buffer_size += n;
  79.     if (!read_buffer)
  80.       read_buffer = (char *)malloc(read_buffer_size);
  81.     else
  82.       read_buffer = (char *)realloc(read_buffer,read_buffer_size);
  83.     if (!read_buffer) out_of_memory("read check");      
  84.     read_buffer_p = read_buffer;      
  85.   }
  86.  
  87.   n = read(f,read_buffer+read_buffer_len,n);
  88.   if (n > 0) {
  89.     read_buffer_len += n;
  90.   }
  91. }
  92.  
  93.  
  94. static int readfd(int fd,char *buffer,int N)
  95. {
  96.   int  ret;
  97.   int total=0;  
  98.  
  99.   while (total < N)
  100.     {
  101.       if (read_buffer_len > 0) {
  102.     ret = MIN(read_buffer_len,N-total);
  103.     memcpy(buffer+total,read_buffer_p,ret);
  104.     read_buffer_p += ret;
  105.     read_buffer_len -= ret;
  106.       } else {
  107.     while ((ret = read(fd,buffer + total,N - total)) == -1) {
  108.       fd_set fds;
  109.  
  110.       if (errno != EAGAIN && errno != EWOULDBLOCK)
  111.         return -1;
  112.       FD_ZERO(&fds);
  113.       FD_SET(fd, &fds);
  114.       select(fd+1, &fds, NULL, NULL, NULL);
  115.     }
  116.       }
  117.  
  118.       if (ret <= 0)
  119.     return total;
  120.       total += ret;
  121.     }
  122.   return total;
  123. }
  124.  
  125.  
  126. int read_int(int f)
  127. {
  128.   int ret;
  129.   char b[4];
  130.   if ((ret=readfd(f,b,4)) != 4) {
  131.     if (verbose > 1) 
  132.       fprintf(FERROR,"(%d) Error reading %d bytes : %s\n",
  133.           getpid(),4,ret==-1?strerror(errno):"EOF");
  134.     exit_cleanup(1);
  135.   }
  136.   total_read += 4;
  137.   return IVAL(b,0);
  138. }
  139.  
  140. void read_buf(int f,char *buf,int len)
  141. {
  142.   int ret;
  143.   if ((ret=readfd(f,buf,len)) != len) {
  144.     if (verbose > 1) 
  145.       fprintf(FERROR,"(%d) Error reading %d bytes : %s\n",
  146.           getpid(),len,ret==-1?strerror(errno):"EOF");
  147.     exit_cleanup(1);
  148.   }
  149.   total_read += len;
  150. }
  151.  
  152. unsigned char read_byte(int f)
  153. {
  154.   unsigned char c;
  155.   read_buf(f,(char *)&c,1);
  156.   return c;
  157. }
  158.  
  159.  
  160. static char last_byte=0;
  161. static int last_sparse = 0;
  162.  
  163. int sparse_end(int f)
  164. {
  165.   if (last_sparse) {
  166.     lseek(f,-1,SEEK_CUR);
  167.     return (write(f,&last_byte,1) == 1 ? 0 : -1);
  168.   }
  169.   last_sparse = 0;
  170.   return 0;
  171. }
  172.  
  173. int write_sparse(int f,char *buf,int len)
  174. {
  175.   int l1=0,l2=0;
  176.   int ret;
  177.  
  178.   if (!sparse_files) 
  179.     return write(f,buf,len);
  180.  
  181.   for (l1=0;l1<len && buf[l1]==0;l1++) ;
  182.   for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
  183.  
  184.   last_byte = buf[len-1];
  185.  
  186.   if (l1 == len || l2 > 0)
  187.     last_sparse=1;
  188.  
  189.   if (l1 > 0)
  190.     lseek(f,l1,SEEK_CUR);  
  191.  
  192.   if (l1 == len) 
  193.     return len;
  194.  
  195.   if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
  196.     if (ret == -1 || ret == 0) return ret;
  197.     return (l1+ret);
  198.   }
  199.  
  200.   if (l2 > 0)
  201.     lseek(f,l2,SEEK_CUR);
  202.  
  203.   return len;
  204. }
  205.  
  206. int read_write(int fd_in,int fd_out,int size)
  207. {
  208.   static char *buf=NULL;
  209.   int bufsize = sparse_files?SPARSE_WRITE_SIZE:WRITE_SIZE;
  210.   int total=0;
  211.   
  212.   if (!buf) {
  213.     buf = (char *)malloc(bufsize);
  214.     if (!buf) out_of_memory("read_write");
  215.   }
  216.  
  217.   while (total < size) {
  218.     int n = MIN(size-total,bufsize);
  219.     read_buf(fd_in,buf,n);
  220.     if (write_sparse(fd_out,buf,n) != n)
  221.       return total;
  222.     total += n;
  223.   }
  224.   return total;
  225. }
  226.  
  227.  
  228. static int writefd(int fd,char *buf,int len)
  229. {
  230.   int total = 0;
  231.   fd_set fds;
  232.   struct timeval tv;
  233.  
  234.   if (buffer_f_in == -1) 
  235.     return write(fd,buf,len);
  236.  
  237.   while (total < len) {
  238.     int ret = write(fd,buf+total,len-total);
  239.  
  240.     if (ret == 0) return total;
  241.  
  242.     if (ret == -1 && !(errno == EWOULDBLOCK || errno == EAGAIN)) 
  243.       return -1;
  244.  
  245.     if (ret == -1) {
  246.       read_check(buffer_f_in);
  247.  
  248.       FD_ZERO(&fds);
  249.       FD_SET(fd,&fds);
  250.       tv.tv_sec = BLOCKING_TIMEOUT;
  251.       tv.tv_usec = 0;
  252.       select(fd+1,NULL,&fds,NULL,&tv);
  253.     } else {
  254.       total += ret;
  255.     }
  256.   }
  257.  
  258.   return total;
  259. }
  260.  
  261.  
  262.  
  263. void write_int(int f,int x)
  264. {
  265.   int ret;
  266.   char b[4];
  267.   SIVAL(b,0,x);
  268.   if ((ret=writefd(f,b,4)) != 4) {
  269.     fprintf(FERROR,"write_int failed : %s\n",
  270.         ret==-1?strerror(errno):"EOF");
  271.     exit_cleanup(1);
  272.   }
  273.   total_written += 4;
  274. }
  275.  
  276. void write_buf(int f,char *buf,int len)
  277. {
  278.   int ret;
  279.   if ((ret=writefd(f,buf,len)) != len) {
  280.     fprintf(FERROR,"write_buf failed : %s\n",
  281.         ret==-1?strerror(errno):"EOF");
  282.     exit_cleanup(1);
  283.   }
  284.   total_written += len;
  285. }
  286.  
  287.  
  288. void write_byte(int f,unsigned char c)
  289. {
  290.   write_buf(f,(char *)&c,1);
  291. }
  292.  
  293. void write_flush(int f)
  294. {
  295. }
  296.  
  297.  
  298.