added comments
[rsync.git] / util.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 void write_int(int f,int x)
43 {
44   char b[4];
45   SIVAL(b,0,x);
46   if (write(f,b,4) != 4) {
47     fprintf(stderr,"write_int failed : %s\n",strerror(errno));
48     exit(1);
49   }
50   total_written += 4;
51 }
52
53 void write_buf(int f,char *buf,int len)
54 {
55   if (write(f,buf,len) != len) {
56     fprintf(stderr,"write_buf failed : %s\n",strerror(errno));
57     exit(1);
58   }
59   total_written += len;
60 }
61
62 static int num_waiting(int fd)
63 {
64   int len=0;
65 #ifdef FIONREAD
66   ioctl(fd,FIONREAD,&len);
67 #endif
68   return(len);
69 }
70
71 static char *read_buffer = NULL;
72 static char *read_buffer_p = NULL;
73 static int read_buffer_len = 0;
74 static int read_buffer_size = 0;
75
76
77 void write_flush(int f)
78 {
79 }
80
81
82 /* This function was added to overcome a deadlock problem when using
83  * ssh.  It looks like we can't allow our receive queue to get full or
84  * ssh will clag up. Uggh.  */
85 void read_check(int f)
86 {
87   int n;
88
89   if (read_buffer_len == 0) {
90     read_buffer_p = read_buffer;
91   }
92
93   if ((n=num_waiting(f)) <= 0)
94     return;
95
96   if (read_buffer_p != read_buffer) {
97     memmove(read_buffer,read_buffer_p,read_buffer_len);
98     read_buffer_p = read_buffer;
99   }
100
101   if (n > (read_buffer_size - read_buffer_len)) {
102     read_buffer_size += n;
103     if (!read_buffer)
104       read_buffer = (char *)malloc(read_buffer_size);
105     else
106       read_buffer = (char *)realloc(read_buffer,read_buffer_size);
107     if (!read_buffer) out_of_memory("read check");      
108     read_buffer_p = read_buffer;      
109   }
110
111   n = read(f,read_buffer+read_buffer_len,n);
112   if (n > 0) {
113     read_buffer_len += n;
114   }
115 }
116
117
118 static int readfd(int fd,char *buffer,int N)
119 {
120   int  ret;
121   int total=0;  
122  
123   while (total < N)
124     {
125       if (read_buffer_len > 0) {
126         ret = MIN(read_buffer_len,N-total);
127         memcpy(buffer+total,read_buffer_p,ret);
128         read_buffer_p += ret;
129         read_buffer_len -= ret;
130       } else {
131         ret = read(fd,buffer + total,N - total);
132       }
133
134       if (ret <= 0)
135         return total;
136       total += ret;
137     }
138   return total;
139 }
140
141
142 int read_int(int f)
143 {
144   char b[4];
145   if (readfd(f,b,4) != 4) {
146     if (verbose > 1) 
147       fprintf(stderr,"Error reading %d bytes : %s\n",4,strerror(errno));
148     exit(1);
149   }
150   total_read += 4;
151   return IVAL(b,0);
152 }
153
154 void read_buf(int f,char *buf,int len)
155 {
156   if (readfd(f,buf,len) != len) {
157     if (verbose > 1) 
158       fprintf(stderr,"Error reading %d bytes : %s\n",len,strerror(errno));
159     exit(1);
160   }
161   total_read += len;
162 }
163
164
165 char *map_file(int fd,off_t len)
166 {
167   char *ret = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
168   return ret;
169 }
170
171 void unmap_file(char *buf,off_t len)
172 {
173   if (len > 0 && buf)
174     munmap(buf,len);
175 }
176
177
178 int read_write(int fd_in,int fd_out,int size)
179 {
180   static char *buf=NULL;
181   static int bufsize = WRITE_BLOCK_SIZE;
182   int total=0;
183   
184   if (!buf) {
185     buf = (char *)malloc(bufsize);
186     if (!buf) out_of_memory("read_write");
187   }
188
189   while (total < size) {
190     int n = MIN(size-total,bufsize);
191     read_buf(fd_in,buf,n);
192     if (write(fd_out,buf,n) != n)
193       return total;
194     total += n;
195   }
196   return total;
197 }
198
199
200 /* this is taken from CVS */
201 int piped_child(char **command,int *f_in,int *f_out)
202 {
203   int pid;
204   int to_child_pipe[2];
205   int from_child_pipe[2];
206
207   if (pipe(to_child_pipe) < 0 ||
208       pipe(from_child_pipe) < 0) {
209     fprintf(stderr,"pipe: %s\n",strerror(errno));
210     exit(1);
211   }
212
213
214   pid = fork();
215   if (pid < 0) {
216     fprintf(stderr,"fork: %s\n",strerror(errno));
217     exit(1);
218   }
219
220   if (pid == 0)
221     {
222       if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
223           close(to_child_pipe[1]) < 0 ||
224           close(from_child_pipe[0]) < 0 ||
225           dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
226         fprintf(stderr,"Failed to dup/close : %s\n",strerror(errno));
227         exit(1);
228       }
229       execvp(command[0], command);
230       fprintf(stderr,"Failed to exec %s : %s\n",
231               command[0],strerror(errno));
232       exit(1);
233     }
234
235   if (close(from_child_pipe[1]) < 0 ||
236       close(to_child_pipe[0]) < 0) {
237     fprintf(stderr,"Failed to close : %s\n",strerror(errno));   
238     exit(1);
239   }
240
241   *f_in = from_child_pipe[0];
242   *f_out = to_child_pipe[1];
243   
244   return pid;
245 }
246
247
248 void out_of_memory(char *str)
249 {
250   fprintf(stderr,"out of memory in %s\n",str);
251   exit(1);
252 }
253
254
255 #ifndef HAVE_STRDUP
256  char *strdup(char *s)
257 {
258   int l = strlen(s) + 1;
259   char *ret = (char *)malloc(l);
260   if (ret)
261     strcpy(ret,s);
262   return ret;
263 }
264 #endif
265
266
267 int set_modtime(char *fname,time_t modtime)
268 {
269 #ifdef HAVE_UTIME_H
270   struct utimbuf tbuf;  
271   tbuf.actime = time(NULL);
272   tbuf.modtime = modtime;
273   return utime(fname,&tbuf);
274 #elif defined(HAVE_UTIME)
275   time_t t[2];
276   t[0] = time(NULL);
277   t[1] = modtime;
278   return utime(fname,t);
279 #else
280   struct timeval t[2];
281   t[0].tv_sec = time(NULL);
282   t[0].tv_usec = 0;
283   t[1].tv_sec = modtime;
284   t[1].tv_usec = 0;
285   return utimes(fname,t);
286 #endif
287 }
288