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