fda04dd87fd8332d16c785fd6dc081cab6779f3f
[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         ret = read(fd,buffer + total,N - total);
107       }
108
109       if (ret <= 0)
110         return total;
111       total += ret;
112     }
113   return total;
114 }
115
116
117 int read_int(int f)
118 {
119   char b[4];
120   if (readfd(f,b,4) != 4) {
121     if (verbose > 1) 
122       fprintf(stderr,"Error reading %d bytes : %s\n",4,strerror(errno));
123     exit(1);
124   }
125   total_read += 4;
126   return IVAL(b,0);
127 }
128
129 void read_buf(int f,char *buf,int len)
130 {
131   if (readfd(f,buf,len) != len) {
132     if (verbose > 1) 
133       fprintf(stderr,"Error reading %d bytes : %s\n",len,strerror(errno));
134     exit(1);
135   }
136   total_read += len;
137 }
138
139 unsigned char read_byte(int f)
140 {
141   char c;
142   read_buf(f,&c,1);
143   return (unsigned char)c;
144 }
145
146 int read_write(int fd_in,int fd_out,int size)
147 {
148   static char *buf=NULL;
149   static int bufsize = WRITE_BLOCK_SIZE;
150   int total=0;
151   
152   if (!buf) {
153     buf = (char *)malloc(bufsize);
154     if (!buf) out_of_memory("read_write");
155   }
156
157   while (total < size) {
158     int n = MIN(size-total,bufsize);
159     read_buf(fd_in,buf,n);
160     if (write(fd_out,buf,n) != n)
161       return total;
162     total += n;
163   }
164   return total;
165 }
166
167
168 static int writefd(int fd,char *buf,int len)
169 {
170   int total = 0;
171   fd_set fds;
172   struct timeval tv;
173
174   if (buffer_f_in == -1) 
175     return write(fd,buf,len);
176
177   while (total < len) {
178     int ret = write(fd,buf+total,len-total);
179
180     if (ret == 0) return total;
181
182     if (ret == -1 && errno != EWOULDBLOCK) 
183       return total?total:-1;
184
185     if (ret == -1) {
186       read_check(buffer_f_in);
187
188       FD_ZERO(&fds);
189       FD_SET(fd,&fds);
190       tv.tv_sec = BLOCKING_TIMEOUT;
191       tv.tv_usec = 0;
192       select(16,NULL,&fds,NULL,&tv);
193     } else {
194       total += ret;
195     }
196   }
197
198   return total;
199 }
200
201
202
203 void write_int(int f,int x)
204 {
205   char b[4];
206   SIVAL(b,0,x);
207   if (writefd(f,b,4) != 4) {
208     fprintf(stderr,"write_int failed : %s\n",strerror(errno));
209     exit(1);
210   }
211   total_written += 4;
212 }
213
214 void write_buf(int f,char *buf,int len)
215 {
216   if (writefd(f,buf,len) != len) {
217     fprintf(stderr,"write_buf failed : %s\n",strerror(errno));
218     exit(1);
219   }
220   total_written += len;
221 }
222
223
224 void write_byte(int f,unsigned char c)
225 {
226   write_buf(f,(char *)&c,1);
227 }
228
229 void write_flush(int f)
230 {
231 }
232
233