*** empty log message ***
[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
32 int write_total(void)
33 {
34   return total_written;
35 }
36
37 int read_total(void)
38 {
39   return total_read;
40 }
41
42 static int buffer_f_in = -1;
43
44 void setup_nonblocking(int f_in,int f_out)
45 {
46   set_blocking(f_out,0);
47   buffer_f_in = f_in;
48 }
49
50
51 static char *read_buffer = NULL;
52 static char *read_buffer_p = NULL;
53 static int read_buffer_len = 0;
54 static int read_buffer_size = 0;
55
56
57 /* This function was added to overcome a deadlock problem when using
58  * ssh.  It looks like we can't allow our receive queue to get full or
59  * ssh will clag up. Uggh.  */
60 static void read_check(int f)
61 {
62   int n;
63
64   if (read_buffer_len == 0) {
65     read_buffer_p = read_buffer;
66   }
67
68   if ((n=num_waiting(f)) <= 0)
69     return;
70
71   if (read_buffer_p != read_buffer) {
72     memmove(read_buffer,read_buffer_p,read_buffer_len);
73     read_buffer_p = read_buffer;
74   }
75
76   if (n > (read_buffer_size - read_buffer_len)) {
77     read_buffer_size += n;
78     if (!read_buffer)
79       read_buffer = (char *)malloc(read_buffer_size);
80     else
81       read_buffer = (char *)realloc(read_buffer,read_buffer_size);
82     if (!read_buffer) out_of_memory("read check");      
83     read_buffer_p = read_buffer;      
84   }
85
86   n = read(f,read_buffer+read_buffer_len,n);
87   if (n > 0) {
88     read_buffer_len += n;
89   }
90 }
91
92
93 static int readfd(int fd,char *buffer,int N)
94 {
95   int  ret;
96   int total=0;  
97  
98   while (total < N)
99     {
100       if (read_buffer_len > 0) {
101         ret = MIN(read_buffer_len,N-total);
102         memcpy(buffer+total,read_buffer_p,ret);
103         read_buffer_p += ret;
104         read_buffer_len -= ret;
105       } else {
106         while ((ret = read(fd,buffer + total,N - total)) == -1) {
107           fd_set fds;
108
109           if (errno != EAGAIN && errno != EWOULDBLOCK)
110             return -1;
111           FD_ZERO(&fds);
112           FD_SET(fd, &fds);
113           select(fd+1, &fds, NULL, NULL, NULL);
114         }
115       }
116
117       if (ret <= 0)
118         return total;
119       total += ret;
120     }
121   return total;
122 }
123
124
125 int read_int(int f)
126 {
127   int ret;
128   char b[4];
129   if ((ret=readfd(f,b,4)) != 4) {
130     if (verbose > 1) 
131       fprintf(stderr,"Error reading %d bytes : %s\n",
132               4,ret==-1?strerror(errno):"EOF");
133     exit_cleanup(1);
134   }
135   total_read += 4;
136   return IVAL(b,0);
137 }
138
139 void read_buf(int f,char *buf,int len)
140 {
141   int ret;
142   if ((ret=readfd(f,buf,len)) != len) {
143     if (verbose > 1) 
144       fprintf(stderr,"Error reading %d bytes : %s\n",
145               len,ret==-1?strerror(errno):"EOF");
146     exit_cleanup(1);
147   }
148   total_read += len;
149 }
150
151 unsigned char read_byte(int f)
152 {
153   char c;
154   read_buf(f,&c,1);
155   return (unsigned char)c;
156 }
157
158
159 static char last_byte=0;
160 static int last_sparse = 0;
161
162 int sparse_end(int f)
163 {
164 #if SPARSE_FILES
165   if (last_sparse) {
166     lseek(f,-1,SEEK_CUR);
167     return (write(f,&last_byte,1) == 1 ? 0 : -1);
168   }
169 #endif  
170   last_sparse = 0;
171   return 0;
172 }
173
174 int write_sparse(int f,char *buf,int len)
175 {
176   int l=0;
177
178 #if SPARSE_FILES
179   for (l=0;l<len && buf[l]==0;l++) ;
180
181   if (l > 0)
182     lseek(f,l,SEEK_CUR);
183
184   last_byte = buf[len-1];
185 #endif
186
187   if (l == len) {
188     last_sparse = 1;
189     return len;
190   } 
191
192   last_sparse = 0;
193
194   return (l + write(f,buf+l,len-l));
195 }
196
197 int read_write(int fd_in,int fd_out,int size)
198 {
199   static char *buf=NULL;
200   static int bufsize = CHUNK_SIZE;
201   int total=0;
202   
203   if (!buf) {
204     buf = (char *)malloc(bufsize);
205     if (!buf) out_of_memory("read_write");
206   }
207
208   while (total < size) {
209     int n = MIN(size-total,bufsize);
210     read_buf(fd_in,buf,n);
211     if (write_sparse(fd_out,buf,n) != n)
212       return total;
213     total += n;
214   }
215   return total;
216 }
217
218
219 static int writefd(int fd,char *buf,int len)
220 {
221   int total = 0;
222   fd_set fds;
223   struct timeval tv;
224
225   if (buffer_f_in == -1) 
226     return write(fd,buf,len);
227
228   while (total < len) {
229     int ret = write(fd,buf+total,len-total);
230
231     if (ret == 0) return total;
232
233     if (ret == -1 && !(errno == EWOULDBLOCK || errno == EAGAIN)) 
234       return -1;
235
236     if (ret == -1) {
237       read_check(buffer_f_in);
238
239       FD_ZERO(&fds);
240       FD_SET(fd,&fds);
241       tv.tv_sec = BLOCKING_TIMEOUT;
242       tv.tv_usec = 0;
243       select(fd+1,NULL,&fds,NULL,&tv);
244     } else {
245       total += ret;
246     }
247   }
248
249   return total;
250 }
251
252
253
254 void write_int(int f,int x)
255 {
256   int ret;
257   char b[4];
258   SIVAL(b,0,x);
259   if ((ret=writefd(f,b,4)) != 4) {
260     fprintf(stderr,"write_int failed : %s\n",
261             ret==-1?strerror(errno):"EOF");
262     exit_cleanup(1);
263   }
264   total_written += 4;
265 }
266
267 void write_buf(int f,char *buf,int len)
268 {
269   int ret;
270   if ((ret=writefd(f,buf,len)) != len) {
271     fprintf(stderr,"write_buf failed : %s\n",
272             ret==-1?strerror(errno):"EOF");
273     exit_cleanup(1);
274   }
275   total_written += len;
276 }
277
278
279 void write_byte(int f,unsigned char c)
280 {
281   write_buf(f,(char *)&c,1);
282 }
283
284 void write_flush(int f)
285 {
286 }
287
288