added resend logic
[rsync/rsync.git] / io.c
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   char c;
155   read_buf(f,&c,1);
156   return (unsigned char)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