standard input on server may be nonblocking
[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(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(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 int read_write(int fd_in,int fd_out,int size)
159 {
160   static char *buf=NULL;
161   static int bufsize = WRITE_BLOCK_SIZE;
162   int total=0;
163   
164   if (!buf) {
165     buf = (char *)malloc(bufsize);
166     if (!buf) out_of_memory("read_write");
167   }
168
169   while (total < size) {
170     int n = MIN(size-total,bufsize);
171     read_buf(fd_in,buf,n);
172     if (write(fd_out,buf,n) != n)
173       return total;
174     total += n;
175   }
176   return total;
177 }
178
179
180 static int writefd(int fd,char *buf,int len)
181 {
182   int total = 0;
183   fd_set fds;
184   struct timeval tv;
185
186   if (buffer_f_in == -1) 
187     return write(fd,buf,len);
188
189   while (total < len) {
190     int ret = write(fd,buf+total,len-total);
191
192     if (ret == 0) return total;
193
194     if (ret == -1 && !(errno == EWOULDBLOCK || errno == EAGAIN)) 
195       return -1;
196
197     if (ret == -1) {
198       read_check(buffer_f_in);
199
200       FD_ZERO(&fds);
201       FD_SET(fd,&fds);
202       tv.tv_sec = BLOCKING_TIMEOUT;
203       tv.tv_usec = 0;
204       select(fd+1,NULL,&fds,NULL,&tv);
205     } else {
206       total += ret;
207     }
208   }
209
210   return total;
211 }
212
213
214
215 void write_int(int f,int x)
216 {
217   int ret;
218   char b[4];
219   SIVAL(b,0,x);
220   if ((ret=writefd(f,b,4)) != 4) {
221     fprintf(stderr,"write_int failed : %s\n",
222             ret==-1?strerror(errno):"EOF");
223     exit(1);
224   }
225   total_written += 4;
226 }
227
228 void write_buf(int f,char *buf,int len)
229 {
230   int ret;
231   if ((ret=writefd(f,buf,len)) != len) {
232     fprintf(stderr,"write_buf failed : %s\n",
233             ret==-1?strerror(errno):"EOF");
234     exit(1);
235   }
236   total_written += len;
237 }
238
239
240 void write_byte(int f,unsigned char c)
241 {
242   write_buf(f,(char *)&c,1);
243 }
244
245 void write_flush(int f)
246 {
247 }
248
249